C++ 使用自定义着色器进行OpenGL/ES渲染=网格上的瑕疵
我试图在屏幕上渲染一个正方形平面网格,分辨率为255 x 255,128个世界单位(读取浮动) 在RAM中分配和填充此网格,将其上载到V-RAM,绑定到属性和索引缓冲区,在其上正确调用C++ 使用自定义着色器进行OpenGL/ES渲染=网格上的瑕疵,c++,opengl,opengl-es,3d,opengl-es-2.0,C++,Opengl,Opengl Es,3d,Opengl Es 2.0,我试图在屏幕上渲染一个正方形平面网格,分辨率为255 x 255,128个世界单位(读取浮动) 在RAM中分配和填充此网格,将其上载到V-RAM,绑定到属性和索引缓冲区,在其上正确调用
不是问题,对象按预期绘制
这是一个水面模拟我的工作和顶点高度得到计算和上传每一帧。当在水面上“点击”时,会产生扰动,然后计算水流并更新法线(考虑从下到上从左到右的水流)
我的问题是,在网格的某些部分,我得到的渲染效果可以在下面的图片中看到(第三个sans消隐)
值得注意的是,在最后一张图片中,效果似乎从视口最左侧的某个位置开始,继续向右延伸另一半宽度。仅当摄影机向左平移时,此效果才可见,在某些相对于网格的位置,但在其他位置不可见,并且摄影机的前进方向或ViewMatrix似乎对瑕疵没有影响。如果我将相机从一边滑动到另一边,我可以注意到工件的原点随着相机移动。该原点似乎位于视口的中心,其高度等于视口的高度,但有时仅为其宽度的四分之一,其他时间则可以达到一半。如前所述,摄影机的前进方向/注视向量对渲染没有影响。即使从“鸟瞰”视图进行渲染,仍然可以观察到效果
似乎相机位置干扰了gl\u position=mat4\u ModelViewProjection*位置代码>
位,或者在顶点颜色计算中,浮点点=点(N,V)代码>
需要某种(怪物)验证吗
以下是我的一些代码:
顶点着色器
"attribute vec2 pos;"
"attribute vec2 normal;"
"attribute float height;"
"uniform vec3 sunColor;"
"uniform float ax;"
"varying PRECISION_MEDIUM vec4 waterColor_;"
"varying PRECISION_LOW vec2 tex_coord;"
"const vec3 g_WaterBlue = vec3( 0.05, 0.25, 0.3 );"
"const vec3 g_WaterGreen = vec3( 0.05, 0.3, 0.2 );"
"vec3 CalculateWaterColor(vec3 V, vec3 N)"
"{"
"float dot = dot(N, V);"
"vec3 waterColor = mix(g_WaterGreen, g_WaterBlue, dot);"
"waterColor = mix(sunColor, waterColor, dot);"
"waterColor = mix(waterColor, g_WaterBlue, dot);"
"return waterColor;"
"}"
"void main()"
"{"
"vec4 position = vec4(pos.x, height, pos.y, 1.0);"
"vec3 V = camera_pos.xyz + camera_forward.xyz - position.xyz;"
"V = normalize(V);"
"vec3 N = vec3(normal.x, 1, normal.y);"
"N = normalize(N);"
"waterColor_.xyz = CalculateWaterColor(V, N);"
"waterColor_.w = 1.0;"//ax * 18 / length(camera_pos.xyz - position.xyz);"
"gl_Position = mat4_ModelViewProjection * position;"
"}"
// LEFT to RIGHT, BOTTOM to TOP
for (index1 = 0; index1 < (Resolution - 1); ++index1)
{
for (index2 = 0; index2 < (Resolution - 1); ++index2)
{
// CLOCKWISE
*++p_data = index2 + index1 * Resolution;
*++p_data = index2 + (index1 + 1) * Resolution;
*++p_data = index2 + 1 + (index1 + 1) * Resolution;
*++p_data = index2 + index1 * Resolution;
*++p_data = index2 + 1 + (index1 + 1) * Resolution;
*++p_data = index2 + 1 + index1 * Resolution;
// COUNTER-CLOCKWISE
//*++p_data = index2 + (index1 + 1) * Resolution;
//*++p_data = index2 + index1 * Resolution;
//*++p_data = index2 + 1 + index1 * Resolution;
//*++p_data = index2 + 1 + index1 * Resolution;
//*++p_data = index2 + 1 + (index1 + 1) * Resolution;
//*++p_data = index2 + (index1 + 1) * Resolution;
// ..
}
}
平面网格顶点生成
// set accelerators
accel1 = Size / static_cast<float>(Resolution - 1);
accel2 = -Size / 2.0f;
x = accel2;
y = accel2;
z = 1.0f;
// ..
// fill the vertex buffer
p_data = reinterpret_cast<float*>(buf_vertex->DataPointer) - 1;
for (index1 = 0; index1 < Resolution; ++index1)
{
for (index2 = 0; index2 < Resolution; ++index2)
{
*++p_data = x;
*++p_data = y;
if (buf_vertex->Dimension == 3)
{
*++p_data = z;
}
x += accel1;
}
x = accel2; // Size / 2
y += accel1;
}
// ..
//设置加速器
accel1=尺寸/静态投影(分辨率-1);
accel2=-Size/2.0f;
x=2;
y=2;
z=1.0f;
// ..
//填充顶点缓冲区
p_data=reinterpret_cast(buf_顶点->数据指针)-1;
对于(index1=0;index1<分辨率;++index1)
{
对于(index2=0;index2<分辨率;++index2)
{
*++p_数据=x;
*++p_数据=y;
如果(buf_顶点->尺寸==3)
{
*++p_数据=z;
}
x+=1;
}
x=accel2;//大小/2
y+=1;
}
// ..
平面网格索引生成器
"attribute vec2 pos;"
"attribute vec2 normal;"
"attribute float height;"
"uniform vec3 sunColor;"
"uniform float ax;"
"varying PRECISION_MEDIUM vec4 waterColor_;"
"varying PRECISION_LOW vec2 tex_coord;"
"const vec3 g_WaterBlue = vec3( 0.05, 0.25, 0.3 );"
"const vec3 g_WaterGreen = vec3( 0.05, 0.3, 0.2 );"
"vec3 CalculateWaterColor(vec3 V, vec3 N)"
"{"
"float dot = dot(N, V);"
"vec3 waterColor = mix(g_WaterGreen, g_WaterBlue, dot);"
"waterColor = mix(sunColor, waterColor, dot);"
"waterColor = mix(waterColor, g_WaterBlue, dot);"
"return waterColor;"
"}"
"void main()"
"{"
"vec4 position = vec4(pos.x, height, pos.y, 1.0);"
"vec3 V = camera_pos.xyz + camera_forward.xyz - position.xyz;"
"V = normalize(V);"
"vec3 N = vec3(normal.x, 1, normal.y);"
"N = normalize(N);"
"waterColor_.xyz = CalculateWaterColor(V, N);"
"waterColor_.w = 1.0;"//ax * 18 / length(camera_pos.xyz - position.xyz);"
"gl_Position = mat4_ModelViewProjection * position;"
"}"
// LEFT to RIGHT, BOTTOM to TOP
for (index1 = 0; index1 < (Resolution - 1); ++index1)
{
for (index2 = 0; index2 < (Resolution - 1); ++index2)
{
// CLOCKWISE
*++p_data = index2 + index1 * Resolution;
*++p_data = index2 + (index1 + 1) * Resolution;
*++p_data = index2 + 1 + (index1 + 1) * Resolution;
*++p_data = index2 + index1 * Resolution;
*++p_data = index2 + 1 + (index1 + 1) * Resolution;
*++p_data = index2 + 1 + index1 * Resolution;
// COUNTER-CLOCKWISE
//*++p_data = index2 + (index1 + 1) * Resolution;
//*++p_data = index2 + index1 * Resolution;
//*++p_data = index2 + 1 + index1 * Resolution;
//*++p_data = index2 + 1 + index1 * Resolution;
//*++p_data = index2 + 1 + (index1 + 1) * Resolution;
//*++p_data = index2 + (index1 + 1) * Resolution;
// ..
}
}
//从左到右,从下到上
对于(index1=0;index1<(分辨率-1);+index1)
{
对于(index2=0;index2<(分辨率-1);+index2)
{
//顺时针
*++p_data=index2+index1*分辨率;
*++p_数据=index2+(index1+1)*分辨率;
*++p_数据=index2+1+(index1+1)*分辨率;
*++p_data=index2+index1*分辨率;
*++p_数据=index2+1+(index1+1)*分辨率;
*++p_data=index2+1+index1*分辨率;
//逆时针
//*++p_数据=index2+(index1+1)*分辨率;
//*++p_data=index2+index1*分辨率;
//*++p_data=index2+1+index1*分辨率;
//*++p_data=index2+1+index1*分辨率;
//*++p_数据=index2+1+(index1+1)*分辨率;
//*++p_数据=index2+(index1+1)*分辨率;
// ..
}
}
我尝试过的事情:
- 启用/禁用深度测试
- 将更大的值设置为深度缓冲区大小(尝试16、32、8——所有值的结果相同)
- 玩弄扑杀
- 玩阿尔法混合
- 深度排序--没用,反正不做混合
- 将大世界大小设置为网格(10000.0f),以避免世界单位(1.0f)百万分之一的舍入误差
- 使用不同的索引缓冲区,以不同的顺序渲染顶点,从上到下,从左到右,以及它们各自的反转——对减弱或加重伪影渲染没有任何影响
- 问题不在发布的代码中——这完全正确
问题是:
// enable blending
glEnable(GL_BLEND);
// ..
glBlendFunc
(
GL_SRC_ALPHA,
GL_ONE_MINUS_SRC_ALPHA
);
GL_ONE_减去SRC_ALPHA应该是GL_ONE,以避免使用此类工件进行绘制
下面是一些更好地理解glBlendFunc工作原理的示例
另外,非常重要的是,在进行混合时,您应该记住禁用glDisable(GL\u DEPTH\u TEST)。问题不在发布的代码中——这都是正确的
问题是:
// enable blending
glEnable(GL_BLEND);
// ..
glBlendFunc
(
GL_SRC_ALPHA,
GL_ONE_MINUS_SRC_ALPHA
);
GL_ONE_减去SRC_ALPHA应该是GL_ONE,以避免使用此类工件进行绘制
下面是一些更好地理解glBlendFunc工作原理的示例
另外,非常重要的是,在进行混合时,您应该记住glDisable(GL\u DEPTH\u TEST)。您是否启用了MSAA?启用后会发生什么情况?将不得不就此向您反馈,因为我没有投入实现裸机win OpenGL上下文之外的任何东西的努力—可以做到,但这需要一些时间——对reside的效果表示怀疑……你打算怎么做?检查我是否从代码中理解:2d位置和高度是独立的属性,但只是属性(高度不是从纹理中采样的,因此采样错误已排除);更改生成索引的方式没有任何效果(因此,索引生成可能不是罪魁祸首)?如果将CPU上的水模拟替换为输出平面或简单的正弦曲线,会发生什么情况?你在多大程度上排除了实际的水模拟