2015-03-17 4 views
2

У меня есть сфера. Я могу отобразить на нем текстуру. Но теперь моя текстура - вне сферы. И мне нужно внутри. Мой пользователь сидит как внутри сферы, поэтому он может просматривать внутри него (вращать и масштабировать). Так просто, как небо купол, но сфера. Может быть, мне нужно исправить координаты текстуры uv или включить что-то?OpenGL ES - текстурирующая сфера

Вот код для генерации сферы:

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; 
    } 
} 

А вот создание ВБО:

+ (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; 
} 
+0

Также у меня есть источник света. Возможно, мне нужно выключить свет, потому что теперь похоже, что внутри сферы темно, не так ли? –

+1

Да, похоже, проблема в светлом положении. Я разрешаю отбраковывать и отключать переднюю грань, и я вижу текстуру по краям, но не по всему объекту. Итак, как я могу исправить источник света? –

+0

Здесь код, как включить переднюю сторону cull: glEnable (GL_CULL_FACE); glCullFace (GL_FRONT); –

ответ

0

Некоторые обезьяны код, но исправить его. Во-первых, мы даем возможность выбраковки и отключить передний боковой рендеринг:

glEnable(GL_CULL_FACE); 
glCullFace(GL_FRONT); 

Тогда я изменить положение источника света:

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

(я даже не нужен свет, поэтому следующий шаг - я должен отключить это вообще). Но, наконец, у меня есть сфера, пользователь внутри нее, может вращать его, увеличивать и уменьшать и видеть текстуру!