OpenGL impostor-sphere:计算深度值时出现问题 [英] OpenGL impostor-sphere : problem when calculating the depth value

查看:22
本文介绍了OpenGL impostor-sphere:计算深度值时出现问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将球体渲染为冒名顶替者,但在计算球体表面点的深度值时遇到问题.

在这里,您可以看到当我围绕冒名顶替球体和与球体相交的真实"立方体移动相机时会发生什么.

你可以看到,当我移动相机时,深度值不一致,立方体的某些部分应该在球体内部,取决于相机的位置,弹出球体.

>

这些是 impostor-sphere 的顶点和片段着色器.

顶点着色器:

#version 450 核心统一的 mat4 模型;统一 mat4 视图;均匀的 mat4 投影;输出 vec2 坐标;无效主(){开关(gl_VertexID){案例0:坐标 = vec2(-1.0f, -1.0f);休息;情况1:坐标 = vec2(-1.0f, +1.0f);休息;案例2:坐标 = vec2(+1.0f, -1.0f);休息;案例3:坐标 = vec2(+1.0f, +1.0f);休息;}//对 &上轴相机空间vec3 right = vec3(view[0][0], view[1][0], view[2][0]);vec3 up = vec3(view[0][1],view[1][1],view[2][1]);vec3 中心 = vec3(0.0f);浮动半径 = 1.0f;//顶点位置vec3 位置 = 半径 * vec3(坐标,0.0f);position = right * position.x + up * position.y;mat4 MVP = 投影 * 视图 * 模型;gl_Position = MVP * vec4(center + position, 1.0f);}

片段着色器:

#version 450 核心统一的 mat4 模型;统一 mat4 视图;均匀的 mat4 投影;在 vec2 坐标中;输出 vec4 像素;无效主(){浮动 d = 点(坐标,坐标);如果 (d > 1.0f){丢弃;}浮动 z = sqrt(1.0f - d);vec3 normal = vec3(coords, z);normal = mat3(transpose((view * model))) * normal;vec3 中心 = vec3(0.0f);浮动半径 = 1.0f;vec3 位置 = 中心 + 半径 * 法线;mat4 MVP = 投影 * 视图 * 模型;//gl_DepthRange.diff 值是远值减去近值vec4 clipPos = MVP * vec4(position, 1.0f);浮动 ndcDepth = clipPos.z/clipPos.w;gl_FragDepth = ((gl_DepthRange.diff * ndcDepth) + gl_DepthRange.near + gl_DepthRange.far) * 0.5f;像素 = vec4((正常 + 1.0f) * 0.5f, 1.0f);}

我按照

我们在 View 处,看着 Point.根据您的冒名顶替者代码,我们将通过将 Point 向前垂直投影到平面直到它碰到球体来计算 Point 的位置.该计算产生了Impostor点.

然而,正如你所看到的,这不是现实显示的.如果我们从 Point 到 View 画一条线(它代表我们应该在那个方向从 View 看到的东西),我们看到的球体上的第一个位置是 Real.而这与 Impostor 相去甚远.

由于根本问题是您的冒名顶替者位置计算错误,唯一的解决方法是使用正确的冒名顶替者计算.正确的方法是(一种或另一种方式)通过从 View 对球体进行光线追踪.这是教程的作用.

I'm trying to render a sphere as an impostor, but I have a problem in calculating the depth value of the points of the sphere's surface.

Here you can see what happens when I move the camera around the impostor-sphere and a "real" cube that intersects the sphere.

You can see that when I move the camera, the depth values are not consistent and some parts of the cube that should be inside the sphere, depending on the position of the camera, pop in and out of the sphere.

These are the vertex and fragment shaders for the impostor-sphere.

vertex shader :

#version 450 core

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

out vec2 coords;

void main()
{
    switch (gl_VertexID)
    {
    case 0:
        coords = vec2(-1.0f, -1.0f);
        break;
    case 1:
        coords = vec2(-1.0f, +1.0f);
        break;
    case 2:
        coords = vec2(+1.0f, -1.0f);
        break;
    case 3:
        coords = vec2(+1.0f, +1.0f);
        break;
    }

    // right & up axes camera space
    vec3 right = vec3(view[0][0], view[1][0], view[2][0]);
    vec3 up = vec3(view[0][1], view[1][1], view[2][1]);

    vec3 center = vec3(0.0f);
    float radius = 1.0f;

    // vertex position
    vec3 position = radius * vec3(coords, 0.0f);
    position = right * position.x + up * position.y;

    mat4 MVP = projection * view * model;
    gl_Position = MVP * vec4(center + position, 1.0f);
}

fragment shader :

#version 450 core

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

in vec2 coords;
out vec4 pixel;

void main()
{
    float d = dot(coords, coords);

    if (d > 1.0f)
    {
        discard;
    }

    float z = sqrt(1.0f - d);

    vec3 normal = vec3(coords, z);
    normal = mat3(transpose((view * model))) * normal;

    vec3 center = vec3(0.0f);
    float radius = 1.0f;

    vec3 position = center + radius * normal;

    mat4 MVP = projection * view * model;

    // gl_DepthRange.diff value is the far value minus the near value

    vec4 clipPos = MVP * vec4(position, 1.0f);
    float ndcDepth = clipPos.z / clipPos.w;
    gl_FragDepth = ((gl_DepthRange.diff * ndcDepth) + gl_DepthRange.near + gl_DepthRange.far) * 0.5f;

    pixel = vec4((normal + 1.0f) * 0.5f, 1.0f);
}

I followed this example to calculate the depth value.

The model matrix that I pass to the shaders is an identity matrix, so it doesn't affect the operations.

Thanks a lot for your help!!

解决方案

Your depth computations are fine. The problem you're having is essentially the same one outlined in the very tutorial you took your depth computations from. It's a different manifestation of that problem, but they all come from the same place: your computation of position is not correct relative to reality. So bad values are being fed to the depth computation; it's no surprise that you're not getting the right result.

This is an exaggerated, 2D representation of your basic problem:

We are at the View, looking at Point. According to your impostor code, we will compute the position for Point by essentially projecting it forward perpendicularly to the plane until it hits the sphere. That computation yields the point Impostor.

However, as you can see, that's not what reality shows. If we draw a line from Point to View (which represents what we should see from View in that direction), the first position on the sphere that we see is Real. And that's very far from Impostor.

Since the fundamental problem is that your impostor position computation is wrong, the only way to fix that is to use a correct impostor computation. And the correct way to do that is (one way or another) through ray-tracing of a sphere from View. Which is what the tutorial does.

这篇关于OpenGL impostor-sphere:计算深度值时出现问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆