Alb*_*ore 1 textures opengl-es effects grayscale
我想渲染一个灰色的颜色纹理.使用着色器在ES 2.0中执行它是件小事,但是可以在ES 1.x中执行吗?
感谢@datenwolf,我这样做:
GLfloat weights_vector[4] = {0.2126, 0.7152, 0.0722, 1.0};
GLfloat additions_vector[4] = {0.5, 0.5, 0.5, 0.0};
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
/* First part */
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_DOT3_RGB);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_CONSTANT);
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, weights_vector);
/* Second part */
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_ADD);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_CONSTANT);
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, additions_vector);
Run Code Online (Sandbox Code Playgroud)
第一部分渲染得很好,如果我自己留下它,但如果我添加第二部分,它使用"黑色"作为前一种颜色,所以我只得到灰色像素.我在这做错了吗?
如果我尝试使用GL_TEXTURE0
而不是GL_PREVIOUS
我确实得到相同的结果GL_TEXTURE
.但是,如果我使用的话,我GL_TEXTURE1
甚至不是灰色像素,而是黑色.我迷路了......
第二部分现在正在运作.应该只是使用@datenwolf建议的以前纹理的名称!
但是,输出仍然不正确,因为它是倒置的.我通过添加:
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_ONE_MINUS_SRC_COLOR);
Run Code Online (Sandbox Code Playgroud)
现在,它太黑了.我无法做对.尝试过但没有用:
我开始怀疑它是不可能的,因为偏见和乘法DOT3_RGB
.在组合器中执行此操作的正确方法是:
GL_DOT3_RGB
例如,而不是使用:
GLfloat weights_vector[4] = {0.30, 0.59, 0.11, 0.0};
Run Code Online (Sandbox Code Playgroud)
使用:
GLfloat weights_vector[4] = {0.575, 0.6475, 0.5275, 0.0};
Run Code Online (Sandbox Code Playgroud)
这确实得到了几乎正确的结果,但是由于第一步以及数字被限制在范围[-1.0,1.0]的事实,一些对比度丢失了
为什么计算?好吧,根据API:
所以我没有看到任何其他方式与我展示的方式不同,并且由于准确性的限制.当然,我可以先将输入除以2.0,然后加0.5,做一个dot3然后再乘以2,从而有效地使所有值都在[-1.0,0.0]范围内.但我担心由于分裂,它仍然会失去准确性.
我怀疑DOT不是为了这个目的而准备的,更有可能只用于碰撞或其他东西.太糟糕了.我希望我错了,但我不明白.
您可以使用点(标量)产品纹理环境.请记住,矢量的点积是
dot(v1, v2) = v1[0]*v2[0] + v1[1]*v2[1] + ... + v1[n]*v2[n]
Run Code Online (Sandbox Code Playgroud)
通过将通道与每个加权因子相加来实现去饱和
L{r,g,b} = w_r * R + w_g * G + w_b * B
Run Code Online (Sandbox Code Playgroud)
但这只不过是带有加权矢量的颜色的点积.OpenGL-1.5有一个称为组合器的纹理环境,这个组合器环境具有点积模式:
GLfloat weighting_vector[4];
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_DOT3_RGB);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_CONSTANT);
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, weighting_vector);
Run Code Online (Sandbox Code Playgroud)
编辑由于评论
您可以在Alpha合并器中的Alpha通道上指定操作,标记为GL_COMBINE_ALPHA.在您的情况下,您只想使用源alpha.添加这些配置:
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE);
Run Code Online (Sandbox Code Playgroud)
我忘了的是,点积模式引入了0.5偏差.但这没有问题,因为你提供了至少3个组合器阶段,所以你得到一个GL_SUBSTRACT阶段减去每个通道的0.5并将你的权重乘以2.0来弥补这一点.
看看该glTexEnv
手册页http://www.opengl.org/sdk/docs/man/xhtml/glTexEnv.xml和原来的扩展规范http://www.opengl.org/registry/specs/ARB/texture_env_combine. txt(这是一个扩展的时间).我承认,如果你是新手,纹理合成器会有点扭曲.从历史上看,它们是片段着色器的前身; NVidia开始使用他们所谓的"寄存器组合器",后来成为纹理组合器.
EDIT2由于附录提问
您必须在其自己的组合器阶段(=纹理单元)中执行第二部分.你切换纹理单位glActiveTexture
.像这样修改你的代码:
GLfloat weights_vector[4] = {0.2126, 0.7152, 0.0722, 1.0};
GLfloat additions_vector[4] = {0.5, 0.5, 0.5, 0.0};
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texID);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
/* First part */
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_DOT3_RGB);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_CONSTANT);
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, weights_vector);
glActiveTexture(GL_TEXTURE1);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texID); // we need some dummy texture active
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
/* Second part */
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_SUBTRACT);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_CONSTANT);
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, additions_vector);
Run Code Online (Sandbox Code Playgroud)
另外我认为你打算减去,补偿0.5偏差而不是加0.5; FTFY.
使用2或3个纹理合成器可以实现这一点.您很可能希望支持仅支持2个纹理合并器的旧设备(例如iPhone 3G).您可以使用以下代码确定设备支持的纹理组合器数量:
int maxTextureUnits;
glGetIntegerv(GL_MAX_TEXTURE_UNITS, &maxTextureUnits);
Run Code Online (Sandbox Code Playgroud)
在没有着色器的情况下实现渲染灰度纹理的基本步骤是:
现在,可以使用Texture Combiner执行这些步骤中的每一个.或者,您也可以只使用两个纹理合并器,将第1步替换为自定义代码,以便在读取纹理时调整像素值.如果您选择仅使用两个纹理合成器,您仍然可以使用颜色渲染调整后的纹理,则只需要一个纹理合并器,在渲染之前将RGB值加倍.
我们为所有像素值添加.5的原因是因为我们用来计算亮度的GL_DOT3_RGB方程将从每个像素值中减去.5.
我们除以2的所有像素值的原因是,使我们的值不被夹紧来自步骤2移动到步骤3,如果我们有(0.5,0.6,0.7)和我们添加0.5到的RGB值时每个RGB值,我们得到的RGB值进入步骤3将是(1.0,1.0,1.0).在DOT3等式从每个值中减去.5之后,它将基于(.5,.5,.5)计算亮度.
下面是使用3个纹理单元渲染纹理灰度的示例代码:
//Enable texture unit 0 to divide RGB values in our texture by 2
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, m_textureId);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glClientActiveTexture(GL_TEXTURE0);
//GL_MODULATE is Arg0 * Arg1
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
//Configure Arg0
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
//Configure Arg1
float multipliers[4] = {.5, .5, .5, 0.0};
glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_CONSTANT);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, (GLfloat*)&multipliers);
//Remember to set your texture coordinates if you need them
//glEnableClientState(GL_TEXTURE_COORD_ARRAY);
//glTexCoordPointer...
//Enable texture unit 1 to increase RGB values by .5
glActiveTexture(GL_TEXTURE1);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, m_textureId);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glClientActiveTexture(GL_TEXTURE1);
//GL_ADD is Arg0 + Arg1
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_ADD);
//Configure Arg0
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
//Configure Arg1
GLfloat additions[4] = {.5, .5, .5, 0.0};
glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_CONSTANT);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, (GLfloat*)&additions);
//Set your texture coordinates if you need them
//glEnableClientState(GL_TEXTURE_COORD_ARRAY);
//glTexCoordPointer...
//Enable texture combiner 2 to get a DOT3_RGB product of your RGB values
glActiveTexture(GL_TEXTURE2);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, m_textureId);
glClientActiveTexture(GL_TEXTURE2);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
//GL_DOT3_RGB is 4*((Arg0r - 0.5) * (Arg1r - 0.5) + (Arg0g - 0.5) * (Arg1g - 0.5) + (Arg0b - 0.5) * (Arg1b - 0.5))
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_DOT3_RGB);
//Configure Arg0
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
//Configure Arg1
//We want this to adjust our DOT3 by R*0.3 + G*0.59 + B*0.11
//So, our actual adjustment will need to take into consideration
//the fact that OpenGL will subtract .5 from our Arg1
//and we need to also take into consideration that we have divided
//our RGB values by 2 and we are multiplying the entire
//DOT3 product by 4
//So, for Red adjustment you will get :
// .65 = (4*(0.3))/2 + 0.5 = (0.3/2) + 0.5
GLfloat weights[4] = {.65, .795, .555, 1.};
glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_CONSTANT);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, (GLfloat*)&weights);
//Set your texture coordinates if you need them
//glEnableClientState(GL_TEXTURE_COORD_ARRAY);
//glTexCoordPointer...
//Render your objects or sprite
//Clean up by disabling your texture combiners or texture units.
glActiveTexture(GL_TEXTURE2);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glDisable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE1);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glDisable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0);
glClientActiveTexture(GL_TEXTURE0);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
2042 次 |
最近记录: |