繁体   English   中英

隧道着色器(从WebGL转换为OpenGL) - 纹理坐标不匹配?

[英]Tunnel shader (converted from WebGL to OpenGL) - texture coords do not match?

我试过上周将来自不同WebGL示例的经典隧道演示效果转换为openFrameroks(使用OpenGL GLSL着色器)。 经过大量的研究,试验和错误,主要是在阅读[本综合教程] [1]和[这一个] [2]后,我仍然不明白为什么转换后的着色器不起作用。 它至少是我认为纹理坐标的问题。

就我对原理的理解而言,你可以通过计算距离中心的角度和距离来获得纹理的像素值,并将它们作为输出传递。 但结果却截然不同。 这是来自我开始尝试的代码的[ShaderToy示例] [3]和[这里是示例] [4]的结果。 以下是我在openFrameworks中得到的内容:![在此处输入图像描述] [5]将纹理传递给着色器:![在此处输入图像描述] [6]看起来这个着色器只是通过像素的顶行暂停一段时间,屏幕保持一种颜色(就像到达隧道的尽头)。 我尝试使用纹理只是颜色噪声作为像素,颜色最后阶段正好是黄色,作为顶行的最后一个像素。 奇怪。 希望有人可以告诉我问题出在哪里。

这是testApp.cpp

void testApp::setup(){

    texture.loadImage("koalaSQ.jpg"); // 512x512px
    tunnel.load("tunnel.vert", "tunnel.frag");
    projection.set(640, 480);
    projection.setPosition(320, 240, 0);
    projection.setResolution(2,2);
    projection.mapTexCoordsFromTexture(texture.getTextureReference());  

 }

void testApp::draw(){
ofSetColor(255);

if (ofGetKeyPressed('g')) // used just for testing texture
{

    ofBackground(0, 0, 0);
    texture.bind();
    projection.draw();
    texture.unbind();

}else
{
    ofBackground(0, 0, 0);
    tunnel.begin();
    tunnel.setUniform1f("timeE", time/1000);
    tunnel.setUniform2f("resolution", 512,512);
    tunnel.setUniformTexture("tex", texture.getTextureReference(), 0);
    projection.draw();

    tunnel.end();


}

time = ofGetElapsedTimeMillis();

}

这是着色器:

 // vertex shader - simple pass-though with texcoodrs as output for fragent shader
#version 150
uniform mat4 modelViewProjectionMatrix;
in vec4 position;
in vec2 texcoord;
out vec2 texC;

void main()
{   
    gl_Position = modelViewProjectionMatrix * position;
    texC = texcoord;
}
// ------------------------Fragent shader----------------------
#version 150
precision highp float;
uniform sampler2DRect tex;
uniform float timeE;
uniform vec2 resolution;
in vec2 texC;
out vec4 output;

void main(){

vec2 position = 2.0 * texC.xy / resolution.xy -1.0;
position.x *= resolution.x / resolution.y;

float a = atan(position.y, position.x);
float r = length(position);

vec2 uv = vec2(1/ r + (timeE*5), a/3.1416);
  vec3 texSample = texture(tex, uv).xyz;
 output = vec4(vec3(texSample), 1);
}

您没有说明许多细节(即您使用texcoord的值)。 但是,我想我仍然可以解释为什么你的代码只导致访问底行(当你使用从上到下的图像数组作为glTexImage()的图像数据时,你可能会认为它是顶行,但从技术上讲,它将是最底行。)

在获取纹理时,您使用uv作为坐标。 你将uv.y定义为atan(position.y, position.x)/3.1415 由于atan()将在[-pi, pi]返回一个vlue,因此将coord大致标准化为区间[-1,1] 经典的OpenGL纹理空间为[0,1] ,其中0表示底行,1表示顶行。 但是,您使用的是sampler2DRect ,因此您使用的是矩形纹理 在这种情况下,tex坐标不是标准化的,而是水平方向上的像素坐标[0,width]和垂直方向上的[0,height]

实际上,您的texcoords确实只在两个纹素的范围内变化。 根据您所设置的包装(和过滤器)模式下,你应该只用clapming,或additionaly(两两行之间或过滤)顶部一行访问底排(或过滤betwenn两个底部行) GL_REPEAT为消极的部分。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM