OpenGL ES - 纹理球体

OpenGL ES - texturing sphere

我有一个球体。我可以在上面映射纹理。但是现在我的纹理在球体之外。我需要里面。我的用户就像在球体内一样坐着,因此他可以在其中查看(旋转和缩放)。所以简单的像一个天穹,而是一个球体。也许我需要修复 uv 纹理坐标或启用某些功能?

这里是生成球体的代码:

    class Sphere : public ParametricSurface {
    public:
        Sphere(float radius) : m_radius(radius)
        {
            ParametricInterval interval = { ivec2(20, 20), vec2(Pi, TwoPi), vec2(8, 14) };
            SetInterval(interval);
        }
        vec3 Evaluate(const vec2& domain) const
        {
            float u = domain.x, v = domain.y;
            float x = m_radius * sin(u) * cos(v);
            float y = m_radius * cos(u);
            float z = m_radius * -sin(u) * sin(v);
            return vec3(x, y, z);
        }
    private:
        float m_radius;
    };

vec2 ParametricSurface::ComputeDomain(float x, float y) const
{
    return vec2(x * m_upperBound.x / m_slices.x, y * m_upperBound.y / m_slices.y);
}

void ParametricSurface::GenerateVertices(float * vertices) const
{
    float* attribute = vertices;
    for (int j = 0; j < m_divisions.y; j++) {
        for (int i = 0; i < m_divisions.x; i++) {

            // Compute Position
            vec2 domain = ComputeDomain(i, j);
            vec3 range = Evaluate(domain);
            attribute = range.Write(attribute);

            // Compute Normal
            if (m_vertexFlags & VertexFlagsNormals) {
                float s = i, t = j;

                // Nudge the point if the normal is indeterminate.
                if (i == 0) s += 0.01f;
                if (i == m_divisions.x - 1) s -= 0.01f;
                if (j == 0) t += 0.01f;
                if (j == m_divisions.y - 1) t -= 0.01f;

                // Compute the tangents and their cross product.
                vec3 p = Evaluate(ComputeDomain(s, t));
                vec3 u = Evaluate(ComputeDomain(s + 0.01f, t)) - p;
                vec3 v = Evaluate(ComputeDomain(s, t + 0.01f)) - p;
                vec3 normal = u.Cross(v).Normalized();
                if (InvertNormal(domain))
                    normal = -normal;
                attribute = normal.Write(attribute);
            }

            // Compute Texture Coordinates
            if (m_vertexFlags & VertexFlagsTexCoords) {
                float s = m_textureCount.x * i / m_slices.x;
                float t = m_textureCount.y * j / m_slices.y;
                attribute = vec2(s, t).Write(attribute);
            }
        }
    }
}

void ParametricSurface::GenerateLineIndices(unsigned short * indices) const
{
    unsigned short * index = indices;
    for (int j = 0, vertex = 0; j < m_slices.y; j++) {
        for (int i = 0; i < m_slices.x; i++) {
            int next = (i + 1) % m_divisions.x;
            *index++ = vertex + i;
            *index++ = vertex + next;
            *index++ = vertex + i;
            *index++ = vertex + i + m_divisions.x;
        }
        vertex += m_divisions.x;
    }
}

void ParametricSurface::GenerateTriangleIndices(unsigned short * indices) const
{
    unsigned short * index = indices;
    for (int j = 0, vertex = 0; j < m_slices.y; j++) {
        for (int i = 0; i < m_slices.x; i++) {
            int next = (i + 1) % m_divisions.x;
            *index++ = vertex + i;
            *index++ = vertex + next;
            *index++ = vertex + i + m_divisions.x;
            *index++ = vertex + next;
            *index++ = vertex + next + m_divisions.x;
            *index++ = vertex + i + m_divisions.x;
        }
        vertex += m_divisions.x;
    }
}

这是 VBO 创建:

+ (DrawableVBO *)createVBO:(SurfaceType)surfaceType
{
    ISurface * surface = [self createSurface:surfaceType]; // just Sphere type

    surface->SetVertexFlags(VertexFlagsNormals | VertexFlagsTexCoords); // which vertexes I need

    // Get vertice from surface.
    //
    int vertexSize = surface->GetVertexSize();
    int vBufSize = surface->GetVertexCount() * vertexSize;
    GLfloat * vbuf = new GLfloat[vBufSize];
    surface->GenerateVertices(vbuf);

    // Get triangle indice from surface
    //
    int triangleIndexCount = surface->GetTriangleIndexCount();
    unsigned short * triangleBuf = new unsigned short[triangleIndexCount];
    surface->GenerateTriangleIndices(triangleBuf);

    // Create the VBO for the vertice.
    //
    GLuint vertexBuffer;
    glGenBuffers(1, &vertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, vBufSize * sizeof(GLfloat), vbuf, GL_STATIC_DRAW);

    // Create the VBO for the triangle indice
    //
    GLuint triangleIndexBuffer;
    glGenBuffers(1, &triangleIndexBuffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, triangleIndexBuffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, triangleIndexCount * sizeof(GLushort), triangleBuf, GL_STATIC_DRAW);

    delete [] vbuf;
    delete [] triangleBuf;
    delete surface;

    DrawableVBO * vbo = [[DrawableVBO alloc] init];
    vbo.vertexBuffer = vertexBuffer;
    vbo.triangleIndexBuffer = triangleIndexBuffer;
    vbo.vertexSize = vertexSize;
    vbo.triangleIndexCount = triangleIndexCount;

    return vbo;
}

这是我的灯光设置:

- (void)setupLights
{
    // Set up some default material parameters.
    //
    glUniform3f(_ambientSlot, 0.04f, 0.04f, 0.04f);
    glUniform3f(_specularSlot, 0.5, 0.5, 0.5);
    glUniform1f(_shininessSlot, 50);

    // Initialize various state.
    //
    glEnableVertexAttribArray(_positionSlot);
    glEnableVertexAttribArray(_normalSlot);

    glUniform3f(_lightPositionSlot, 1.0, 1.0, 5.0);

    glVertexAttrib3f(_diffuseSlot, 0.8, 0.8, 0.8);
}

最后是着色器: 片段:

precision mediump float;

varying vec4 vDestinationColor;
varying vec2 vTextureCoordOut;

uniform sampler2D Sampler;

void main()
{
    gl_FragColor = texture2D(Sampler, vTextureCoordOut) * vDestinationColor;
}

顶点:

uniform mat4 projection;
uniform mat4 modelView;
attribute vec4 vPosition;
attribute vec2 vTextureCoord;

uniform mat3 normalMatrix;
uniform vec3 vLightPosition;
uniform vec3 vAmbientMaterial;
uniform vec3 vSpecularMaterial;
uniform float shininess;

attribute vec3 vNormal;
attribute vec3 vDiffuseMaterial;

varying vec4 vDestinationColor;
varying vec2 vTextureCoordOut;

void main(void)
{
    gl_Position = projection * modelView * vPosition;

    vec3 N = normalMatrix * vNormal;
    vec3 L = normalize(vLightPosition);
    vec3 E = vec3(0, 0, 1);
    vec3 H = normalize(L + E);

    float df = max(0.0, dot(N, L));
    float sf = max(0.0, dot(N, H));
    sf = pow(sf, shininess);

    vec3 color = vAmbientMaterial + df * vDiffuseMaterial + sf * vSpecularMaterial;
    vDestinationColor = vec4(color, 1);

    vTextureCoordOut = vTextureCoord;
}

一些猴子代码,但我修复了他的。首先我们启用剔除并禁用前端渲染:

glEnable(GL_CULL_FACE); 
glCullFace(GL_FRONT);

然后我改变光源的位置:

glUniform3f(_lightPositionSlot, 1.0, 1.0, -2.5);

(我什至不需要灯,所以下一步 - 我必须完全禁用它)。但最后我有一个球体,用户在里面,可以旋转它,放大和缩小并查看纹理!