简体   繁体   English

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

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

I tried for past week to convert classic tunnel demo effect from different WebGL examples to openFrameroks (using OpenGL GLSL shader). 我试过上周将来自不同WebGL示例的经典隧道演示效果转换为openFrameroks(使用OpenGL GLSL着色器)。 After a lot of research, trials and errors and mainly after reading [this comprehensive tutorial][1] and [this one as well][2], I still do not understand why converted shader is not working. 经过大量的研究,试验和错误,主要是在阅读[本综合教程] [1]和[这一个] [2]后,我仍然不明白为什么转换后的着色器不起作用。 It aprears to be some sort of problem with texture coordinates, at least I think. 它至少是我认为纹理坐标的问题。

As far as my understanding of principle goes, you get pixel values from texture by calculating angle and distance from center and pass them as output. 就我对原理的理解而言,你可以通过计算距离中心的角度和距离来获得纹理的像素值,并将它们作为输出传递。 But results are way different. 但结果却截然不同。 Here is result from [ShaderToy example][3] and [here is example][4] from code I started experimenting with. 这是来自我开始尝试的代码的[ShaderToy示例] [3]和[这里是示例] [4]的结果。 And here is what I got in openFrameworks: ![enter image description here][5] with this as texture passed to shader: ![enter image description here][6] It seems like that shader is just going through top row of pixels, bacause after a while, screen stays at one color (it like reaching end of the tunnel). 以下是我在openFrameworks中得到的内容:![在此处输入图像描述] [5]将纹理传递给着色器:![在此处输入图像描述] [6]看起来这个着色器只是通过像素的顶行暂停一段时间,屏幕保持一种颜色(就像到达隧道的尽头)。 I tried use texture just with color noise as pixels and color final stage was exactly yellow, as last pixel in top row. 我尝试使用纹理只是颜色噪声作为像素,颜色最后阶段正好是黄色,作为顶行的最后一个像素。 Strange. 奇怪。 Hopefully someone can tell me where the problem is. 希望有人可以告诉我问题出在哪里。

Here is testApp.cpp 这是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();

}

and here are shaders: 这是着色器:

 // 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);
}

There are lots of details you did not state (ie what values you use for texcoord). 您没有说明许多细节(即您使用texcoord的值)。 However, I think I can still explain why your code results in only accessing the bottom row (you might think of it as the top row when you use an top-to-bottom image array as the image data for glTexImage() , but technically, it will be the bottom row.) 但是,我想我仍然可以解释为什么你的代码只导致访问底行(当你使用从上到下的图像数组作为glTexImage()的图像数据时,你可能会认为它是顶行,但从技术上讲,它将是最底行。)

You are using uv as the coords when fetching the texture. 在获取纹理时,您使用uv作为坐标。 And you define uv.y to be atan(position.y, position.x)/3.1415 . 你将uv.y定义为atan(position.y, position.x)/3.1415 Since atan() will return a vlue in [-pi, pi] , you normalize the coord roughly to the interval [-1,1] . 由于atan()将在[-pi, pi]返回一个vlue,因此将coord大致标准化为区间[-1,1] The classical OpenGL texture space is [0,1] , where 0 would be the bottom row and 1 the top row. 经典的OpenGL纹理空间为[0,1] ,其中0表示底行,1表示顶行。 However, you are using sampler2DRect , so you are using rectangle textures . 但是,您使用的是sampler2DRect ,因此您使用的是矩形纹理 In that case, the tex coords are not normalized, but the pixel coords [0,width] in horizontal direction and [0,height] in vertical direction. 在这种情况下,tex坐标不是标准化的,而是水平方向上的像素坐标[0,width]和垂直方向上的[0,height]

In effect, your texcoords do vary only in the range of two texels. 实际上,您的texcoords确实只在两个纹素的范围内变化。 Depending on what wrap (and filter) modes you have set, you should only access the bottom row (or filtering betwenn the two bottom rows) with clapming, or additionaly the top row (or filtering between the two top rows) with GL_REPEAT for the negative parts. 根据您所设置的包装(和过滤器)模式下,你应该只用clapming,或additionaly(两两行之间或过滤)顶部一行访问底排(或过滤betwenn两个底部行) GL_REPEAT为消极的部分。

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

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