gpt4 book ai didi

opengl-es - 在 OpenGL ES 中绘制一个球体

转载 作者:行者123 更新时间:2023-12-03 21:02:59 25 4
gpt4 key购买 nike

我想绘制一个球体,我知道如何使用 glBegin() 和 glEnd() 等调用在 OpenGL 中进行绘制。

但是 ES 中什么都没有。

建议/教程链接?

最佳答案

既然你已经用 OpenGL ES 2.0 标记了它,让我建议另一种创建平滑球体的方法,那就是将它们绘制为光线追踪的冒名顶替者。无需计算复制光滑球体所需的许多顶点,您可以利用球体从任何角度看起来都几乎相同的事实。

为此,您需要使用如下流程:

Sphere impostor generation

您将表示两个三角形的四个顶点发送到顶点着色器,然后将它们置换以创建始终面向用户的正方形。在该正方形内,您使用片段着色器在每个像素上进行光栅化,并提供球体在该点上的颜色,如果您通过此正方形窗口查看它。

这种方法的优点是球体与显示器支持的分辨率一样平滑,并且球体可以轻松地从小到大缩放,而无需重新计算几何图形。它确实将渲染的负担从顶点处理器转移到片段处理器,但对于单个球体,这在我使用过的 OpenGL ES 2.0 设备上并不是什么大问题。

我在 this iOS application 中使用了这种技术,在那个页面上有源代码,多说几句here .我使用的顶点着色器的简化版本如下所示:

attribute vec4 position;
attribute vec4 inputImpostorSpaceCoordinate;

varying mediump vec2 impostorSpaceCoordinate;
varying mediump vec3 normalizedViewCoordinate;

uniform mat4 modelViewProjMatrix;
uniform mediump mat4 orthographicMatrix;
uniform mediump float sphereRadius;

void main()
{
vec4 transformedPosition;
transformedPosition = modelViewProjMatrix * position;
impostorSpaceCoordinate = inputImpostorSpaceCoordinate.xy;

transformedPosition.xy = transformedPosition.xy + inputImpostorSpaceCoordinate.xy * vec2(sphereRadius);
transformedPosition = transformedPosition * orthographicMatrix;

normalizedViewCoordinate = (transformedPosition.xyz + 1.0) / 2.0;
gl_Position = transformedPosition;
}

简化的片段着色器是这样的:
precision mediump float;

uniform vec3 lightPosition;
uniform vec3 sphereColor;
uniform mediump float sphereRadius;

uniform sampler2D depthTexture;

varying mediump vec2 impostorSpaceCoordinate;
varying mediump vec3 normalizedViewCoordinate;

const mediump vec3 oneVector = vec3(1.0, 1.0, 1.0);

void main()
{
float distanceFromCenter = length(impostorSpaceCoordinate);

// Establish the visual bounds of the sphere
if (distanceFromCenter > 1.0)
{
discard;
}

float normalizedDepth = sqrt(1.0 - distanceFromCenter * distanceFromCenter);

// Current depth
float depthOfFragment = sphereRadius * 0.5 * normalizedDepth;
// float currentDepthValue = normalizedViewCoordinate.z - depthOfFragment - 0.0025;
float currentDepthValue = (normalizedViewCoordinate.z - depthOfFragment - 0.0025);

// Calculate the lighting normal for the sphere
vec3 normal = vec3(impostorSpaceCoordinate, normalizedDepth);

vec3 finalSphereColor = sphereColor;

// ambient
float lightingIntensity = 0.3 + 0.7 * clamp(dot(lightPosition, normal), 0.0, 1.0);
finalSphereColor *= lightingIntensity;

// Per fragment specular lighting
lightingIntensity = clamp(dot(lightPosition, normal), 0.0, 1.0);
lightingIntensity = pow(lightingIntensity, 60.0);
finalSphereColor += vec3(0.4, 0.4, 0.4) * lightingIntensity;

gl_FragColor = vec4(finalSphereColor, 1.0);
}

这些着色器的当前优化版本有点难以遵循,而且我还使用了环境光遮挡照明,这些都没有。同样未显示的是该球体的纹理,这可以通过适当的映射函数在球体表面坐标和矩形纹理之间进行转换来完成。这就是我为球体表面提供预先计算的环境遮挡值的方式。

关于opengl-es - 在 OpenGL ES 中绘制一个球体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10488086/

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