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

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

问题描述

我试图将球体作为冒充者,但在计算球体表面点的深度值时遇到问题.

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

您可以看到,当我移动照相机时,深度值不一致,并且应根据照相机的位置,将立方体的某些部分放置在球体内部.

>

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

顶点着色器:

  #version 450内核统一的mat4模型;统一的mat4视图;均匀的mat4投影;vec2协调员;无效main(){开关(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 center = vec3(0.0f);浮点半径= 1.0f;//顶点位置vec3位置=半径* vec3(坐标,0.0f);position =右侧* position.x +向上* position.y;mat4 MVP =投影*视图*模型;gl_Position = MVP * vec4(中心+位置,1.0f);} 

片段着色器:

  #version 450内核统一的mat4模型;统一的mat4视图;均匀的mat4投影;在vec2协调中;出vec4像素;无效main(){浮点数d =点(coords,coords);如果(d> 1.0f){丢弃;}float z = sqrt(1.0f-d);vec3 normal = vec3(coords,z);正常= mat3(transpose((view * model)))*正常;vec3 center = vec3(0.0f);浮点半径= 1.0f;vec3位置=中心+半径*正常;mat4 MVP =投影*视图*模型;//gl_DepthRange.diff值是远值减去近值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;像素= vec4((normal + 1.0f)* 0.5f,1.0f);} 

我按照

我们正在查看,看着Point.根据您的冒名顶替者代码,我们将通过将Point垂直垂直于平面向前投影直到到达球体来计算Point的位置.计算得出点为Impostor.

但是,正如您所看到的,这不是现实所显示的.如果我们从点到视图画一条线(代表我们应该从该方向看到的线),则我们在球体上看到的第一个位置是实数.那与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天全站免登陆