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

标签 c++ opengl glsl webgl openframeworks

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

就我对原理的理解而言,您可以通过计算与中心的角度和距离来从纹理中获取像素值,并将它们作为输出传递。但结果却大不相同。 这是 [ShaderToy 示例][3] 的结果,[这里是示例][4] 来 self 开始试验的代码。这是我在 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,因此您可以将坐标大致标准化为区间 [-1,1]。经典的 OpenGL 纹理空间是 [0,1],其中 0 表示底行,1 表示顶行。但是,您使用的是 sampler2DRect,所以您使用的是 rectangle textures .在那种情况下,tex 坐标未被归一化,但像素坐标 [0,width] 在水平方向和 [0,height] 在垂直方向。

实际上,您的纹理坐标确实只在两个 纹理元素的范围内变化。根据您设置的换行(和过滤)模式,您应该只通过拍手访问底行(或在底两行之间过滤),或者使用 访问顶行(或在两行之间过滤) GL_REPEAT 负数部分。

关于c++ - 隧道着色器(从 WebGL 转换为 OpenGL)- 纹理坐标不匹配?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20029702/

相关文章:

c - 在 GLSL 中使用多个纹理+滤镜

c++ - C++ 中的线程安全日志缓冲区?

c++ - 获取 sf::View 的 X 和 Y 偏移量

c++ - 高效优雅的接口(interface)抽象

opengl - 访问片段着色器中的重心坐标

javascript - 为什么这个 Webgl 示例中的光在移动

c++ - 如何在OpenGL中绘制由5个三角形组成的VAO?

c++ - 在 Qt 中从一种形式导航到另一种形式

opengl - 发送 GL 制服 : Multiple floats vs packing into vector

opengl - FBO 和 mipmap 纹理