gpt4 book ai didi

c++ - 如何使用MVP在OpenGL中绘制椭圆

转载 作者:行者123 更新时间:2023-12-01 14:52:37 27 4
gpt4 key购买 nike

如何绘制圆/椭圆并使用“模型- View -投影”进行变换。

我用glDrawElements(GL_TRIANGLES, ...)在一个矩形中绘制一个椭圆。

我制作了一个着色器,它可以工作,但是如何对其进行转换?

顶点着色器

#version 330 core

layout (location = 0) in vec2 position;

void main()
{
gl_Position = vec4(position, 0.0, 1.0);
}

片段着色器

#version 400 core

uniform mat4 u_mvp;
uniform vec2 u_resolution;
out vec4 color;

float pow2(float x) { return x * x; }

void main()
{
vec2 d = (gl_FragCoord.xy / u_resolution.xy) * 2 - vec2(1.0);
vec4 pos = vec4(d, 0.0, 0.0);
vec4 center = vec4(0.0);

float r = distance(pos, center);
r = step(0.5, r);
color = vec4(0.7f, 0.8f, 0.1f, 1.0f - r);
}

如何添加MVP支持?

最佳答案

有多种选择,可以实现您想要的。它们的基础是创建一个与射线和球面相交的函数。
以下算法取自Peter Shirley'sRay Tracing in One Weekend
射线由origindirection定义。球体由center点和radius定义:

float hit_sphere(vec3 origin, vec3 direction, vec3 center, float radius)
{
vec3 oc = origin - center;
float a = dot(direction, direction);
float b = 2.0 * dot(oc, direction);
float c = dot(oc, oc) - radius*radius;
float discriminant = b*b - 4*a*c;

if (discriminant > 0.0)
{
float temp = (-b - sqrt(discriminant)) / (2*a);
if (temp > 0.0)
return 1.0;
temp = (-b + sqrt(discriminant)) / (2*a);
if (temp > 0.0)
return 1.0;
}
return 0.0;
}

计算射线上的2点。带有xy坐标 xy = gl_FragCoord.xy / u_resolution.xy * 2.0 - 1.0的归一化设备空间中的每个点都在同一条射线上。 vec4(xy, -1.0, 1.0)在近平面上,而 vec4(xy, 1.0, 1.0)在远平面上。通过 inverse 模型 View 投影矩阵( u_mvp)转换这些点,然后将 xyz分量除以 w分量,以在笛卡尔坐标系的模型空间中获得射线。
调整算法的大小可以计算射线上的2个点,这适用于透视投影和正交投影。

vec4 pn = inverse(u_mvp) * vec4(xy, -1.0, 1.0);
vec4 pf = inverse(u_mvp) * vec4(xy, 1.0, 1.0);

vec3 orig = pn.xyz/pn.w;
vec3 dir = pf.xyz/pf.w - orig;

使用射线在模型空间中相交球体:

vec3  center = vec3(0.0);
float radius = 1.0;
float r = hit_sphere(orig, dir, center, radius);

我已经使用 View 矩阵 glm::translate(glm::mat4(1), glm::vec3(0, 0, -3))和投影矩阵 glm::perspective(glm::radians(90), aspect, 0.1, 10.0)测试了该算法

片段着色器:

#version 330 core

out vec4 frag_color;

uniform mat4 u_mvp;
uniform vec2 u_resolution;

float hit_sphere(vec3 origin, vec3 direction, vec3 center, float radius)
{
vec3 oc = origin - center;
float a = dot(direction, direction);
float b = 2.0 * dot(oc, direction);
float c = dot(oc, oc) - radius*radius;
float discriminant = b*b - 4*a*c;

if (discriminant > 0.0)
{
float temp = (-b - sqrt(discriminant)) / (2*a);
if (temp > 0.0)
return 1.0;
temp = (-b + sqrt(discriminant)) / (2*a);
if (temp > 0.0)
return 1.0;
}
return 0.0;
}

void main()
{
vec2 xy = gl_FragCoord.xy / u_resolution.xy * 2.0 - 1.0;

vec4 pn = inverse(u_mvp) * vec4(xy, -1.0, 1.0);
vec4 pf = inverse(u_mvp) * vec4(xy, 1.0, 1.0);

vec3 orig = pn.xyz/pn.w;
vec3 dir = pf.xyz/pf.w - orig;

vec3 center = vec3(0.0);
float radius = 1.0;
float r = hit_sphere(orig, dir, center, radius);

vec4 backcolor = vec4(0.2, 0.3, 0.3, 1.0);
vec4 color = vec4(0.7, 0.8, 0.1, 1.0);

frag_color = mix(backcolor, color, r);
}

关于c++ - 如何使用MVP在OpenGL中绘制椭圆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62134349/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com