Opengles着色器插值问题
Opengles shaders interpolation issue
我发现了与着色器插值精度相关的问题。由于着色器对可变变量(在本例中为高度)的插值精度,我得到一条扭曲的蓝线,如下所示。我该如何解决?
这是我将数据提供给着色器的方式:
uint8_t * oglData = CVPixelBufferGetBaseAddress(_pixelBuffer);
for (NSInteger i = 0; i < 256; i++) {
/* Only first two columns blue in BGRA 256x1 buffer */
if (i < 2) {
oglData[4 * i] = 255;
oglData[4 * i + 1] = 0;
oglData[4 * i +2] = 0;
oglData[4 * i +3] = 1;
} else {
oglData[4 * i] = 0;
oglData[4 * i + 1] = 0;
oglData[4 * i +2] = 0;
oglData[4 * i +3] = 1;
}
}
}
这里是着色器:
顶点着色器:
attribute vec4 position;
attribute vec4 inputTextureCoordinate;
varying vec2 textureCoordinate;
varying float height;
void main()
{
gl_Position = position;
textureCoordinate = vec2(inputTextureCoordinate.x, 0.0);
height = inputTextureCoordinate.y;
}
片段着色器:
varying highp vec2 textureCoordinate;
varying highp float height;
uniform sampler2D inputImageTexture;
uniform lowp vec4 backgroundColor;
void main() {
lowp vec3 colorChannels = texture2D(inputImageTexture, textureCoordinate).rgb;
//
if (colorChannels.b >= height) {
gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);
} else {
gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
}
}
下面是绘图代码:
glActiveTexture( GL_TEXTURE0 );
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, oglData);
glUniform1i( _inputImageTexture, 0 );
// Set texture parameters
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
glVertexAttribPointer( ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, squareVertices );
glEnableVertexAttribArray( ATTRIB_VERTEX );
glVertexAttribPointer( ATTRIB_TEXTURECOORDINATE, 2, GL_FLOAT, 0, 0, textureCoordinates );
glEnableVertexAttribArray( ATTRIB_TEXTURECOORDINATE );
glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
glBindRenderbuffer( GL_RENDERBUFFER, _colorBufferHandle );
[_oglContext presentRenderbuffer:GL_RENDERBUFFER];
编辑:将 GL_LINEAR 更改为 GL_NEAREST 解决了这个问题,这意味着根据纹理参数中最小和放大过滤器的类型对不同的变量进行插值?但是使用 GL_Nearest 会创建不平滑的曲线。
How do I fix it?
你不能(至少不能直接)- 这是 GPU 内部的固定功能硬件,所以你只能忍受它。
Changing GL_LINEAR to GL_NEAREST fixes the issue, which means varying vars are interpolated based on the type of min & mag filters in texture parameters?
否 - 变化的插值与纹理 min/mag 过滤器无关。
你的问题是变化插值的不准确性导致输入到你的 texture()
函数调用的样本点偏离纹素中心,所以 GL_LINEAR
纹理过滤开始有效果。
通过使用 GL_NEAREST
你可以有效地量化采样点,所以只要误差小于半个纹素宽度,你就可以快速返回到你想要的纹素。
我发现了与着色器插值精度相关的问题。由于着色器对可变变量(在本例中为高度)的插值精度,我得到一条扭曲的蓝线,如下所示。我该如何解决?
这是我将数据提供给着色器的方式:
uint8_t * oglData = CVPixelBufferGetBaseAddress(_pixelBuffer);
for (NSInteger i = 0; i < 256; i++) {
/* Only first two columns blue in BGRA 256x1 buffer */
if (i < 2) {
oglData[4 * i] = 255;
oglData[4 * i + 1] = 0;
oglData[4 * i +2] = 0;
oglData[4 * i +3] = 1;
} else {
oglData[4 * i] = 0;
oglData[4 * i + 1] = 0;
oglData[4 * i +2] = 0;
oglData[4 * i +3] = 1;
}
}
}
这里是着色器:
顶点着色器:
attribute vec4 position;
attribute vec4 inputTextureCoordinate;
varying vec2 textureCoordinate;
varying float height;
void main()
{
gl_Position = position;
textureCoordinate = vec2(inputTextureCoordinate.x, 0.0);
height = inputTextureCoordinate.y;
}
片段着色器:
varying highp vec2 textureCoordinate;
varying highp float height;
uniform sampler2D inputImageTexture;
uniform lowp vec4 backgroundColor;
void main() {
lowp vec3 colorChannels = texture2D(inputImageTexture, textureCoordinate).rgb;
//
if (colorChannels.b >= height) {
gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);
} else {
gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
}
}
下面是绘图代码:
glActiveTexture( GL_TEXTURE0 );
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, oglData);
glUniform1i( _inputImageTexture, 0 );
// Set texture parameters
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
glVertexAttribPointer( ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, squareVertices );
glEnableVertexAttribArray( ATTRIB_VERTEX );
glVertexAttribPointer( ATTRIB_TEXTURECOORDINATE, 2, GL_FLOAT, 0, 0, textureCoordinates );
glEnableVertexAttribArray( ATTRIB_TEXTURECOORDINATE );
glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
glBindRenderbuffer( GL_RENDERBUFFER, _colorBufferHandle );
[_oglContext presentRenderbuffer:GL_RENDERBUFFER];
编辑:将 GL_LINEAR 更改为 GL_NEAREST 解决了这个问题,这意味着根据纹理参数中最小和放大过滤器的类型对不同的变量进行插值?但是使用 GL_Nearest 会创建不平滑的曲线。
How do I fix it?
你不能(至少不能直接)- 这是 GPU 内部的固定功能硬件,所以你只能忍受它。
Changing GL_LINEAR to GL_NEAREST fixes the issue, which means varying vars are interpolated based on the type of min & mag filters in texture parameters?
否 - 变化的插值与纹理 min/mag 过滤器无关。
你的问题是变化插值的不准确性导致输入到你的 texture()
函数调用的样本点偏离纹素中心,所以 GL_LINEAR
纹理过滤开始有效果。
通过使用 GL_NEAREST
你可以有效地量化采样点,所以只要误差小于半个纹素宽度,你就可以快速返回到你想要的纹素。