将 Sampler2D 与着色器一起使用时出现问题
Issue with using Sampler2D with a Shader
!我知道有比这更容易绘制到屏幕上的方法,但我需要以这种特定方式进行!
我正在通过 fbo 绘制纹理。
然后我使用着色器将它重新绘制到屏幕上,使用 sampler2D(纹理)这样做,并将着色器设置 gl_fragColor 到片段着色器所在特定点的 sampler2D 的颜色.
我遇到的问题是显示缓冲区(着色器将 fbo 绘制到其中)只是纯蓝色,即使我用蓝色背景向 fbo 绘制了一个白色方块。
我的代码:
主渲染循环:
while(!Display.isCloseRequested()){
//Drawing on the fbo a blue background and white square
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboID);
glColor3f(0,0,1);
drawQuad(0,0,WIDTH,HEIGHT);
glColor3f(1,1,1);
drawQuad(0,0,50,50);
//Trying to draw the texture from the previous fbo
//on to the display buffer with a fragment shader,
//however it only draws a blue background, no white square.
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
GL13.glActiveTexture(GL13.GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D,texID);
glUseProgram(shaderProgram);
glUniform1i(glGetUniformLocation(shaderProgram, "tex"), 0);
glUniform1f(glGetUniformLocation(shaderProgram, "width"), WIDTH);
glUniform1f(glGetUniformLocation(shaderProgram, "height"), HEIGHT);
glBegin(GL_QUADS); {
glVertex2f(0, 0);
glVertex2f(0, HEIGHT);
glVertex2f(WIDTH, HEIGHT);
glVertex2f(WIDTH, 0);
} glEnd();
glUseProgram(0);
Display.update();
}
我的着色器:
uniform sampler2D tex;
uniform float width;
uniform float height;
void main() {
vec4 color = texture2D( tex, gl_FragCoord.xy / vec2(width, height));
gl_FragColor = color;
}
fbo 的初始化方法:
texID=glGenTextures();
fboID=glGenFramebuffersEXT();
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboID);
glBindTexture(GL_TEXTURE_2D, texID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, WIDTH, HEIGHT, 0,GL_RGBA, GL_INT, (java.nio.ByteBuffer) null);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,GL_COLOR_ATTACHMENT0_EXT,GL_TEXTURE_2D, texID, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
我认为发生这种情况的一个原因可能是因为我没有正确地将 Sampler2D 传递给着色器,但我不确定如何修复它。
如果有人能说出为什么会发生这种情况或如何解决它(甚至只是正确方向上的一点),我们将不胜感激!
(抱歉英语不好!)
您已将呼叫转接到 glUniform1i (...)
和 glUseProgram (...)
。
在执行 glUniform1i(glGetUniformLocation(shaderProgram, "tex"), 0);
时,当前活动的程序是 0 实际上应该会产生以下错误:
GL_INVALID_OPERATION
is generated if there is no current program object.
如果你交换上面提到的两行,那应该可以解决你的问题。将来你应该在某些东西不工作时检查 glGetError (...)
。
更新:既然原来的问题已经解决,你没有正确设置纹理缩小过滤器。
要设置枚举数,您必须使用glTexParameteri (...)
。 glTexParameterf (...)
会将传递的值解释为浮点数,并且 GL_LINEAR
(0x2601) 的类型为 GLenum
(32 位无符号整数).幸运的是,所有核心 OpenGL 枚举只使用低 16 位,因此它们可以精确地表示为 32 位浮点数(可以表示最大为 224 的所有整数),但你可以明白为什么不想将整数常量转换为浮点数。
因此,下面一行:
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
需要:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
更新 2:使用 texture2D (...)
.
时必须使用归一化纹理坐标
gl_FragCoord.xy
的范围是 [0, width
] 和 [0, height
],这超出了任何大于 1x1 的帧缓冲区的标准化范围。要解决这个问题,您必须除以宽度和高度。
texelFetch (...)
允许您使用非标准化坐标,但它需要 GLSL 1.30,您必须将 gl_FragCoord.xy
转换为 ivec2
才能使用它。如果您绘制的 FBO 尺寸与您的 window.
不同,也可能会带来不便
!我知道有比这更容易绘制到屏幕上的方法,但我需要以这种特定方式进行!
我正在通过 fbo 绘制纹理。 然后我使用着色器将它重新绘制到屏幕上,使用 sampler2D(纹理)这样做,并将着色器设置 gl_fragColor 到片段着色器所在特定点的 sampler2D 的颜色.
我遇到的问题是显示缓冲区(着色器将 fbo 绘制到其中)只是纯蓝色,即使我用蓝色背景向 fbo 绘制了一个白色方块。
我的代码:
主渲染循环:
while(!Display.isCloseRequested()){
//Drawing on the fbo a blue background and white square
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboID);
glColor3f(0,0,1);
drawQuad(0,0,WIDTH,HEIGHT);
glColor3f(1,1,1);
drawQuad(0,0,50,50);
//Trying to draw the texture from the previous fbo
//on to the display buffer with a fragment shader,
//however it only draws a blue background, no white square.
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
GL13.glActiveTexture(GL13.GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D,texID);
glUseProgram(shaderProgram);
glUniform1i(glGetUniformLocation(shaderProgram, "tex"), 0);
glUniform1f(glGetUniformLocation(shaderProgram, "width"), WIDTH);
glUniform1f(glGetUniformLocation(shaderProgram, "height"), HEIGHT);
glBegin(GL_QUADS); {
glVertex2f(0, 0);
glVertex2f(0, HEIGHT);
glVertex2f(WIDTH, HEIGHT);
glVertex2f(WIDTH, 0);
} glEnd();
glUseProgram(0);
Display.update();
}
我的着色器:
uniform sampler2D tex;
uniform float width;
uniform float height;
void main() {
vec4 color = texture2D( tex, gl_FragCoord.xy / vec2(width, height));
gl_FragColor = color;
}
fbo 的初始化方法:
texID=glGenTextures();
fboID=glGenFramebuffersEXT();
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboID);
glBindTexture(GL_TEXTURE_2D, texID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, WIDTH, HEIGHT, 0,GL_RGBA, GL_INT, (java.nio.ByteBuffer) null);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,GL_COLOR_ATTACHMENT0_EXT,GL_TEXTURE_2D, texID, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
我认为发生这种情况的一个原因可能是因为我没有正确地将 Sampler2D 传递给着色器,但我不确定如何修复它。
如果有人能说出为什么会发生这种情况或如何解决它(甚至只是正确方向上的一点),我们将不胜感激!
(抱歉英语不好!)
您已将呼叫转接到 glUniform1i (...)
和 glUseProgram (...)
。
在执行 glUniform1i(glGetUniformLocation(shaderProgram, "tex"), 0);
时,当前活动的程序是 0 实际上应该会产生以下错误:
GL_INVALID_OPERATION
is generated if there is no current program object.
如果你交换上面提到的两行,那应该可以解决你的问题。将来你应该在某些东西不工作时检查 glGetError (...)
。
更新:既然原来的问题已经解决,你没有正确设置纹理缩小过滤器。
要设置枚举数,您必须使用glTexParameteri (...)
。 glTexParameterf (...)
会将传递的值解释为浮点数,并且 GL_LINEAR
(0x2601) 的类型为 GLenum
(32 位无符号整数).幸运的是,所有核心 OpenGL 枚举只使用低 16 位,因此它们可以精确地表示为 32 位浮点数(可以表示最大为 224 的所有整数),但你可以明白为什么不想将整数常量转换为浮点数。
因此,下面一行:
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
需要:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
更新 2:使用 texture2D (...)
.
gl_FragCoord.xy
的范围是 [0, width
] 和 [0, height
],这超出了任何大于 1x1 的帧缓冲区的标准化范围。要解决这个问题,您必须除以宽度和高度。
texelFetch (...)
允许您使用非标准化坐标,但它需要 GLSL 1.30,您必须将 gl_FragCoord.xy
转换为 ivec2
才能使用它。如果您绘制的 FBO 尺寸与您的 window.