将 Sampler2D 与着色器一起使用的问题
Posted
技术标签:
【中文标题】将 Sampler2D 与着色器一起使用的问题【英文标题】:Issue with using Sampler2D with a Shader 【发布时间】:2015-03-14 14:01:36 【问题描述】:!我知道有比这更简单的方法来绘制到屏幕上,但我需要以这种特定的方式来做!
我正在通过 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 传递给着色器,但我不知道如何修复它。
如果有人能说出为什么会发生这种情况或如何解决它(甚至只是朝着正确方向的一点),我们将不胜感激!
(对不起,英语不好!)
【问题讨论】:
固定管道,即像glBegin)/glEnd()
这样的函数不会与编程管道(着色器)混合。你不能同时使用两者
@Amadeus:可以,只是不能在核心配置文件中使用这些功能。确实和固定功能操作无关;立即模式在 OpenGL 3.0 中被弃用并在 3.1 中被删除。当然,固定功能管道也同时被弃用和删除,因此您可能很容易将两者等同起来。
@AndonM.Coleman 是的,你可以,但它可以或不能渲染到屏幕上,这会给你带来难以找到的错误
如果glBegin (...)
、glEnd (...)
和朋友是固定功能管道的一部分,那将是真的,但他们不是。它们完全存在于渲染管道之外,它们将顶点状态打包在一起,并在第一阶段(顶点处理)开始之前定义原始拓扑。作为固定功能管道一部分的一个例子是顶点照明,它曾经在顶点变换期间应用。
【参考方案1】:
您已将呼叫转接到glUniform1i (...)
和glUseProgram (...)
。
在执行glUniform1i(glGetUniformLocation(shaderProgram, "tex"), 0);
时,当前活动的程序是0,实际上应该产生以下错误:
如果没有当前程序对象,则生成
GL_INVALID_OPERATION
。
如果您交换上面提到的两行,那应该可以解决您的问题。以后当某些东西不起作用时,您应该注意检查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 的尺寸与您的窗口不同,这也可能会带来不便。
【讨论】:
@Meta:你能把分配纹理的代码添加到你的FBO的GL_COLOR_ATTACHMENT0
吗?
我为fbo添加了init方法,是这个意思吗?
我换了行,但它仍然不起作用:(我用你的更新更新 q
如果我上传整个课程会有帮助吗?
@Meta:顺便说一句,你以后真的不应该这样编辑你的问题。我的答案所指的原始代码完全消失了。如果您对问题进行了更改,则应保留原始代码并提及您更改的代码行。以上是关于将 Sampler2D 与着色器一起使用的问题的主要内容,如果未能解决你的问题,请参考以下文章
在片段着色器中,为啥我不能使用平面输入整数来索引 sampler2D 的统一数组?
纹理同时用作着色器程序的 FBO 颜色附件和 sampler2D