[英]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.