Math 投影理论?(在GLSL中实施)

Math 投影理论?(在GLSL中实施),math,opengl,glsl,projection,Math,Opengl,Glsl,Projection,OpenGL3.x,因为我不想在技术上落后太多 首先,是的,我知道很多。 我几乎可以肯定vec3 transform(vec3)函数是好的,如果我不知道的话 它不包含我来这里的问题 我遇到问题的代码位是(或应该是)在vec3项目(vec3)函数中。 如果我直接看,比如说,一个盒子,它看起来很好。如果我把相机转一转,盒子就会 靠近屏幕的一侧(视野),我的快乐盒子开始变成一个长方形。 虽然这是我可以忍受的游戏,我把它投入,这是恼人的 投影背后的基本理论是:你有一个点(x,y,z),你找到它和原点(相

OpenGL3.x,因为我不想在技术上落后太多

首先,是的,我知道很多。 我几乎可以肯定
vec3 transform(vec3)
函数是好的,如果我不知道的话 它不包含我来这里的问题

我遇到问题的代码位是(或应该是)在
vec3项目(vec3)
函数中。 如果我直接看,比如说,一个盒子,它看起来很好。如果我把相机转一转,盒子就会 靠近屏幕的一侧(视野),我的快乐盒子开始变成一个长方形。 虽然这是我可以忍受的游戏,我把它投入,这是恼人的

投影背后的基本理论是:你有一个点(x,y,z),你找到它和原点(相机所在的位置)之间的角度,然后将它投影到一个距离
较近的平面上。
找到角度是一个
angleX=atan(x/z)
angleY=atan(y/z)
的问题。使用这两个角度,通过执行
point=tan(angle)*nearz
将它们投影到近平面上。然后通过
edgeY=tan(fovy)*nearz
edgeX=tan(fovy*aspect)*nearz>找到屏幕的外脊。使用
screen=point/edge

作为一个基本的优化,我已经做了,但为了解决这个问题,我删除了这个优化,只需要取
screen=angle/fov

我的投影函数理论有问题吗? 以下是实现:

#version 330

uniform vec3 model_location = vec3(0.0, 0.0, 0.0);
uniform vec3 model_rotation = vec3(0.0, 0.0, 0.0);
uniform vec3 model_scale    = vec3(1.0, 1.0, 1.0);

uniform vec3 camera_location = vec3(0.0, 0.0, 0.0);
uniform vec3 camera_rotation = vec3(0.0, 0.0, 0.0);
uniform vec3 camera_scale    = vec3(1.0, 1.0, 1.0);

uniform float fovy   =   60.0;
uniform float nearz  =    0.01;
uniform float farz   = 1000.0;
uniform float aspect =    1.0;

vec3 transform(vec3 point)
{
    vec3 translate = model_location - camera_location;
    vec3 rotate    = radians(model_rotation);
    vec3 scale     = model_scale    / camera_scale;

    vec3 s = vec3(sin(rotate.x), sin(rotate.y), sin(rotate.z));
    vec3 c = vec3(cos(rotate.x), cos(rotate.y), cos(rotate.z));

    float sy_cz = s.y * c.z;
    float sy_sz = s.y * s.z;
    float cx_sz = c.x * s.z;

    vec3 result;
    result.x = ( point.x * ( ( c.y * c.z ) * scale.x ) ) + ( point.y * ( ( ( -cx_sz )    + ( s.x * sy_cz ) )    * scale.y ) ) + ( point.z * ( ( ( -s.x * s.z ) + ( c.x * sy_cz ) ) * scale.z ) ) + translate.x;
    result.y = ( point.x * ( ( c.y * s.z ) * scale.y ) ) + ( point.y * ( ( ( c.x * c.z ) + ( s.x * sy_sz ) )    * scale.y ) ) + ( point.z * ( ( ( -s.x * c.z ) + ( c.x * sy_sz ) ) * scale.z ) ) + translate.y;
    result.z = ( point.x * ( ( -s.y )      * scale.x ) ) + ( point.y * ( (   s.x * c.y )                        * scale.y ) ) + ( point.z * ( (    c.x * c.y )                     * scale.z ) ) + translate.z;

    return result;
}

vec4 project(vec3 point)
{
    vec4 result = vec4(0.0);

    vec3 rotation = radians(camera_rotation);

    result.x = ( atan(point.x/point.z) - rotation.y );
    result.y = ( atan(point.y/point.z) - rotation.x );
    result.z = point.z/(farz - nearz);
    result.w = 1.0;

    result.x = tan(result.x) * nearz;
    result.y = tan(result.y) * nearz;

    vec2 bounds = vec2( tan(fovy * aspect) * nearz,
                        tan(fovy) * nearz );

    result.x = result.x / bounds.x;
    result.y = result.y / bounds.y;

    if (camera_rotation.z == 0)
        return result;

    float dist = sqrt( (result.x*result.x) + (result.y*result.y) );
    float theta = atan(result.y/result.x) + rotation.z;
    result.x = sin(theta) * dist;
    result.y = cos(theta) * dist;

    return result;
}

layout(location = 0) in vec3 vertex_position;
layout(location = 1) in vec2 texCoord;

out vec2 uvCoord;

void main()
{
    uvCoord = texCoord;
    vec4 pos = project( transform(vertex_position) );

    if (pos.z < 0.0)
        return;
    gl_Position = pos;
}
#版本330
均匀vec3模型_位置=vec3(0.0,0.0,0.0);
均匀vec3模型_旋转=vec3(0.0,0.0,0.0);
统一vec3模型_比例=vec3(1.0,1.0,1.0);
均匀vec3摄像机位置=vec3(0.0,0.0,0.0);
均匀vec3摄像机旋转=vec3(0.0,0.0,0.0);
均匀vec3摄像机_标度=vec3(1.0,1.0,1.0);
均匀浮动fovy=60.0;
在Z附近均匀浮动=0.01;
均匀浮动法氏=1000.0;
均匀浮动方向=1.0;
vec3变换(vec3点)
{
vec3 translate=模型位置-摄像机位置;
vec3旋转=弧度(模型旋转);
vec3比例=模型比例/摄像机比例;
vec3s=vec3(sin(rotate.x)、sin(rotate.y)、sin(rotate.z));
vec3c=vec3(cos(rotate.x)、cos(rotate.y)、cos(rotate.z));
浮动sy_cz=s.y*c.z;
浮点数sy_sz=s.y*s.z;
浮点数cx_sz=c.x*s.z;
vec3结果;
结果x=(点x*((c.y*c.z)*标度x))+(点y*((-cx_sz)+(s.x*sy_cz))*scale.y))+(点z*((-s.x*s.z)+(c.x*sy_cz))*scale.x);
结果y=(点x*((c.y*s.z)*标度.y)+(点y*((c.x*c.z)+(s.x*sy_sz))*scale.y)+(点z*((-s.x*c.z)+(c.x*sy_sz))*scale.z)+平移.y;
结果.z=(点x*(-s.y)*标度.x))+(点y*((s.x*c.y)*标度.y))+(点z*((c.x*c.y)*标度.z))+translate.z;
返回结果;
}
vec4项目(vec3点)
{
vec4结果=vec4(0.0);
vec3旋转=弧度(摄像机旋转);
结果.x=(atan(点.x/点.z)-旋转.y);
结果y=(atan(点y/点z)-旋转.x);
结果.z=点.z/(farz-nearz);
结果:w=1.0;
结果x=tan(结果x)*nearz;
结果y=tan(结果y)*nearz;
vec2边界=vec2(棕褐色(fovy*aspect)*nearz,
谭(福维)*nearz;
result.x=result.x/bounds.x;
result.y=result.y/bounds.y;
如果(摄影机旋转.z==0)
返回结果;
float dist=sqrt((result.x*result.x)+(result.y*result.y));
浮点θ=atan(result.y/result.x)+旋转.z;
结果x=sin(θ)*距离;
结果y=cos(θ)*距离;
返回结果;
}
vec3顶点位置的布局(位置=0);
vec2 texCoord中的布局(位置=1);
输出vec2-uvCoord;
void main()
{
uvCoord=texCoord;
vec4 pos=项目(变换(顶点位置));
如果(位置z<0.0)
返回;
gl_位置=位置;
}
要回答几个预期的问题:

问:为什么不使用GLM/其他数学库

A:

-我刚才试过了。我的“Hello world!”三角形卡在屏幕中央。使用转换矩阵并没有将其向前移动、缩放或其他任何操作

-因为学习如何为自己找出问题的答案是很重要的。 这意味着我学会了如何处理这样的事情 如果一切都失控,有什么可以依靠的。 (这是一个愚蠢的理由。)

问:为什么不使用矩阵

A:

-那些人也恨我

-我正在用一种新的方法来做,如果我使用矩阵,那么我将以正确的方式来做 每一个教程都说我应该去做,而不是自己去想

资料来源:

从第288-293页的“OpenGL着色语言第三版”、“模拟OpenGL固定功能”中逐字复制GLSL着色器(vert和frag)

每一个都试了很多次,每一个都修修补补到了疯狂的地步。 为了编写一个战争游戏,我得到了一个金属线框,用它投射到和平符号中

编辑:

正如datenwolf所指出的,问题在于使用了极坐标。更好的等式 为了进行投影,使用不太高级的数学是:
c=zNear*(p.x/p.y)
根据两个三角形的概念,投影点三角形和给定点 三角形,是介词;因此,使用相同的角度

假设为要投影的点指定了X和Y,并且它们的前置三角形Sides分别标记为A和C。 你可以取等式的
atan(Y/X)=角度
atan(C/A)=角度
atan(Y/X)=atan(C/A)
然后变成 result.x = ( point.x * ( ( c.y * c.z ) * scale.x ) ) + ( point.y * ( ( ( -cx_sz ) + ( s.x * sy_cz ) ) * scale.y ) ) + ( point.z * ( ( ( -s.x * s.z ) + ( c.x * sy_cz ) ) * scale.z ) ) + translate.x; result.y = ( point.x * ( ( c.y * s.z ) * scale.y ) ) + ( point.y * ( ( ( c.x * c.z ) + ( s.x * sy_sz ) ) * scale.y ) ) + ( point.z * ( ( ( -s.x * c.z ) + ( c.x * sy_sz ) ) * scale.z ) ) + translate.y; result.z = ( point.x * ( ( -s.y ) * scale.x ) ) + ( point.y * ( ( s.x * c.y ) * scale.y ) ) + ( point.z * ( ( c.x * c.y ) * scale.z ) ) + translate.z;