为什么移动视图矩阵垂直垂直移动我的圆,但不能水平移动,以及如何使其完全不移动?

发布于 2025-02-02 21:28:11 字数 5329 浏览 5 评论 0原文

我有一个正在处理的游戏引擎。现在,我正试图渲染圈子。我使用以下格式为其编写顶点数据:

    0       1       2 3 4 5 6         7
v = xOffset yOffset r g b a ssboIndex r

这些是我的着色器:

vertex着色器

#version 450 core

layout(location = 0) uniform mat4 uProjectionView;
layout(location = 1) uniform vec2 uViewDimensions;
layout(location = 2) uniform mat4 uProjection;
layout(location = 3) uniform mat4 uView;

layout(std430, binding = 3) buffer shaderStorageBuffer {
    mat4 transform[];
};

layout(location = 0) in vec2 positionOffset;
layout(location = 1) in vec4 color;
layout(location = 2) in float ssboID;
layout(location = 3) in float radius;

out vec2 vertexVPositionOffset;
out vec4 vertexVColor;
out unsigned int vertexVSSBOID;
out float vertexVRadius;

void main() {
    vertexVPositionOffset = positionOffset;
    vertexVColor = color;
    vertexVSSBOID = int(ssboID);
    vertexVRadius = radius;

    // vertexVNormalizedCenter = (uProjectionView * transform[int(ssboID)] * vec4(positionOffset, 0, 1)).xy;
    // vertexVNormalizedRadius = (uProjectionView * vec4(radius, radius, 0, 0)).xy;
}

几何>几何>

#version 450 core

layout (points) in;
layout (triangle_strip, max_vertices = 5) out;

layout(location = 0) uniform mat4 uProjectionView;
layout(location = 1) uniform vec2 uViewDimensions;
layout(location = 2) uniform mat4 uProjection;
layout(location = 3) uniform mat4 uView;

layout(std430, binding = 3) buffer shaderStorageBuffer {
    mat4 transform[];
};

in vec2 vertexVPositionOffset[];
in vec4 vertexVColor[];
in unsigned int vertexVSSBOID[];
in float vertexVRadius[];

out vec4 geometryVColor;
out float geometryVRadius;
out vec2 geometryVCenter;

void main() {
    geometryVRadius = vertexVRadius[0];
    geometryVCenter = (transform[int(vertexVSSBOID[0])] * vec4(vertexVPositionOffset[0], 0, 1)).xy;
    geometryVColor = vertexVColor[0];

    vec2 position;

    position = (uProjectionView * transform[int(vertexVSSBOID[0])] * vec4(vertexVPositionOffset[0].x - geometryVRadius, vertexVPositionOffset[0].y - geometryVRadius, 0, 1)).xy;
    gl_Position = vec4(position, 0, 1);
    EmitVertex();

    position = (uProjectionView * transform[int(vertexVSSBOID[0])] * vec4(vertexVPositionOffset[0].x + geometryVRadius, vertexVPositionOffset[0].y - geometryVRadius, 0, 1)).xy;
    gl_Position = vec4(position, 0, 1);
    EmitVertex();

    position = (uProjectionView * transform[int(vertexVSSBOID[0])] * vec4(vertexVPositionOffset[0].x + geometryVRadius, vertexVPositionOffset[0].y + geometryVRadius, 0, 1)).xy;
    gl_Position = vec4(position, 0, 1);
    EmitVertex();

    position = (uProjectionView * transform[int(vertexVSSBOID[0])] * vec4(vertexVPositionOffset[0].x - geometryVRadius, vertexVPositionOffset[0].y + geometryVRadius, 0, 1)).xy;
    gl_Position = vec4(position, 0, 1);
    EmitVertex();

    position = (uProjectionView * transform[int(vertexVSSBOID[0])] * vec4(vertexVPositionOffset[0].x - geometryVRadius, vertexVPositionOffset[0].y - geometryVRadius, 0, 1)).xy;
    gl_Position = vec4(position, 0, 1);
    EmitVertex();

    EndPrimitive();
}

fragment着色器

#version 450 core

layout(location = 0) uniform mat4 uProjectionView;
layout(location = 1) uniform vec2 uViewDimensions;
layout(location = 2) uniform mat4 uProjection;
layout(location = 3) uniform mat4 uView;

layout(std430, binding = 3) buffer shaderStorageBuffer {
    mat4 transform[];
};

in vec4 geometryVColor;
in float geometryVRadius;
in vec2 geometryVCenter;

layout(location = 0) out vec4 color;

void main() {
    // vec4 pixelInWorldCoordinate = inverse(uProjection) * vec4(gl_FragCoord.x / (uViewDimensions.x / 2.0f) - 1, 1 - gl_FragCoord.y / (uViewDimensions.y / 2.0f), 0, 1);
    vec4 view = vec4(gl_FragCoord.x / (uViewDimensions.x / 2.0f) - 1, 1 - gl_FragCoord.y / (uViewDimensions.y / 2.0f), 0, 1);
    vec4 pixelInWorldCoordinate = inverse(uProjectionView) * view;
    
    // float d = sqrt(pow(pixelInWorldCoordinate.x - geometryVCenter.x, 2) + pow(-pixelInWorldCoordinate.y - geometryVCenter.y, 2));
    // if (d < geometryVRadius)
    //  color = geometryVColor;
    // else
    //  discard;
    
    float leftExpression = pow(pixelInWorldCoordinate.x - geometryVCenter.x, 2) + pow(pixelInWorldCoordinate.y + geometryVCenter.y, 2);
    float rightExpression = pow(geometryVRadius, 2);
    if (leftExpression <= rightExpression)
        color = geometryVColor;
    else
        discard;
}

这就是没有的样子移动相机: 现在,如果我垂直移动相机,则会发生: 但是,如果相机水平移动,一切都很好: 为什么会发生这种情况?我花了无数小时的时间尝试解决这个问题。

注意:背景中渲染的白色正方形是分别渲染的参考广场。它与圆的顶点位置匹配。 如果需要,我可以添加更多上下文。

更多上下文: 投影矩阵正在用Glortho生成。 查看矩阵是一个代表相机翻译并乘以投影矩阵的身份矩阵。 视图尺寸是窗口的宽度和高度。 在片段着色器中,我将片段坐标转换为世界坐标,以查看片段是否在圆内,以决定是否需要渲染它。 同样,移动圆圈的转换矩阵没有任何问题。仅当我垂直移动相机时才发生。

I have a game engine I am working on. Right now, I am trying to render circles. I write vertex data to it using the following format:

    0       1       2 3 4 5 6         7
v = xOffset yOffset r g b a ssboIndex r

These are my shaders:

Vertex Shader

#version 450 core

layout(location = 0) uniform mat4 uProjectionView;
layout(location = 1) uniform vec2 uViewDimensions;
layout(location = 2) uniform mat4 uProjection;
layout(location = 3) uniform mat4 uView;

layout(std430, binding = 3) buffer shaderStorageBuffer {
    mat4 transform[];
};

layout(location = 0) in vec2 positionOffset;
layout(location = 1) in vec4 color;
layout(location = 2) in float ssboID;
layout(location = 3) in float radius;

out vec2 vertexVPositionOffset;
out vec4 vertexVColor;
out unsigned int vertexVSSBOID;
out float vertexVRadius;

void main() {
    vertexVPositionOffset = positionOffset;
    vertexVColor = color;
    vertexVSSBOID = int(ssboID);
    vertexVRadius = radius;

    // vertexVNormalizedCenter = (uProjectionView * transform[int(ssboID)] * vec4(positionOffset, 0, 1)).xy;
    // vertexVNormalizedRadius = (uProjectionView * vec4(radius, radius, 0, 0)).xy;
}

Geometry Shader

#version 450 core

layout (points) in;
layout (triangle_strip, max_vertices = 5) out;

layout(location = 0) uniform mat4 uProjectionView;
layout(location = 1) uniform vec2 uViewDimensions;
layout(location = 2) uniform mat4 uProjection;
layout(location = 3) uniform mat4 uView;

layout(std430, binding = 3) buffer shaderStorageBuffer {
    mat4 transform[];
};

in vec2 vertexVPositionOffset[];
in vec4 vertexVColor[];
in unsigned int vertexVSSBOID[];
in float vertexVRadius[];

out vec4 geometryVColor;
out float geometryVRadius;
out vec2 geometryVCenter;

void main() {
    geometryVRadius = vertexVRadius[0];
    geometryVCenter = (transform[int(vertexVSSBOID[0])] * vec4(vertexVPositionOffset[0], 0, 1)).xy;
    geometryVColor = vertexVColor[0];

    vec2 position;

    position = (uProjectionView * transform[int(vertexVSSBOID[0])] * vec4(vertexVPositionOffset[0].x - geometryVRadius, vertexVPositionOffset[0].y - geometryVRadius, 0, 1)).xy;
    gl_Position = vec4(position, 0, 1);
    EmitVertex();

    position = (uProjectionView * transform[int(vertexVSSBOID[0])] * vec4(vertexVPositionOffset[0].x + geometryVRadius, vertexVPositionOffset[0].y - geometryVRadius, 0, 1)).xy;
    gl_Position = vec4(position, 0, 1);
    EmitVertex();

    position = (uProjectionView * transform[int(vertexVSSBOID[0])] * vec4(vertexVPositionOffset[0].x + geometryVRadius, vertexVPositionOffset[0].y + geometryVRadius, 0, 1)).xy;
    gl_Position = vec4(position, 0, 1);
    EmitVertex();

    position = (uProjectionView * transform[int(vertexVSSBOID[0])] * vec4(vertexVPositionOffset[0].x - geometryVRadius, vertexVPositionOffset[0].y + geometryVRadius, 0, 1)).xy;
    gl_Position = vec4(position, 0, 1);
    EmitVertex();

    position = (uProjectionView * transform[int(vertexVSSBOID[0])] * vec4(vertexVPositionOffset[0].x - geometryVRadius, vertexVPositionOffset[0].y - geometryVRadius, 0, 1)).xy;
    gl_Position = vec4(position, 0, 1);
    EmitVertex();

    EndPrimitive();
}

Fragment Shader

#version 450 core

layout(location = 0) uniform mat4 uProjectionView;
layout(location = 1) uniform vec2 uViewDimensions;
layout(location = 2) uniform mat4 uProjection;
layout(location = 3) uniform mat4 uView;

layout(std430, binding = 3) buffer shaderStorageBuffer {
    mat4 transform[];
};

in vec4 geometryVColor;
in float geometryVRadius;
in vec2 geometryVCenter;

layout(location = 0) out vec4 color;

void main() {
    // vec4 pixelInWorldCoordinate = inverse(uProjection) * vec4(gl_FragCoord.x / (uViewDimensions.x / 2.0f) - 1, 1 - gl_FragCoord.y / (uViewDimensions.y / 2.0f), 0, 1);
    vec4 view = vec4(gl_FragCoord.x / (uViewDimensions.x / 2.0f) - 1, 1 - gl_FragCoord.y / (uViewDimensions.y / 2.0f), 0, 1);
    vec4 pixelInWorldCoordinate = inverse(uProjectionView) * view;
    
    // float d = sqrt(pow(pixelInWorldCoordinate.x - geometryVCenter.x, 2) + pow(-pixelInWorldCoordinate.y - geometryVCenter.y, 2));
    // if (d < geometryVRadius)
    //  color = geometryVColor;
    // else
    //  discard;
    
    float leftExpression = pow(pixelInWorldCoordinate.x - geometryVCenter.x, 2) + pow(pixelInWorldCoordinate.y + geometryVCenter.y, 2);
    float rightExpression = pow(geometryVRadius, 2);
    if (leftExpression <= rightExpression)
        color = geometryVColor;
    else
        discard;
}

This is how it looks like without moving the camera:
enter image description here
Now, if I move the camera vertically, this happens:
enter image description here
But everything is fine if the camera moves horizontally:
enter image description here
Why is this happening? I have spent countless hours trying to fix this with no success.

Note: the white square rendered in the background is a reference square being rendered separately. It matches the vertex positions of the circle.
I can add more context if needed.

More context:
Projection matrix is being generated with glortho.
View matrix is an identity matrix to represent the camera translation and is multiplied by projection matrix.
View dimensions are the width and height of the window.
In the fragment shader, I am converting the fragment coordinate to world coordinate to see if the fragment is inside the circle to decide whether or not it needs to be rendered.
Also, moving the circle's transformation matrix does not have any problem. It only happens when I move the camera vertically.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文