忘记 UIImage/等。如果您使用 OpenGL 渲染 3D 立方体,则必须使用 OpenGL 纹理对其进行纹理映射。这些都是 OpenGL 中非常基本的东西;网上肯定有很多关于 1. 纹理映射和 2. 绘制立方体的教程。
确保搜索“OpenGL ES 1.1”、“OpenGL ES 2.0”或“GLKit”
编辑
试试这个:http ://www.raywenderlich.com/4404/opengl-es-2-0-for-iphone-tutorial-part-2-textures
编辑 2
好的,一些源代码。首先,我使用这种顶点数据格式:
typedef struct tTextureCoords
{
GLfloat s;
GLfloat t;
}TextureCoords;
// 3D Float Vector for Position and Normals
typedef struct tVertex3D
{
GLfloat x;
GLfloat y;
GLfloat z;
}Vertex3D;
// 4D Byte Vector for Colors
typedef struct tColor4
{
GLubyte r; // [0...255]
GLubyte g; // [0...255]
GLubyte b; // [0...255]
GLubyte a; // [0...255]
}Color4;
// Vertex Data for 3D Objects
typedef struct tVertexData3D
{
Vertex3D position;
Vertex3D normal;
TextureCoords texCoords;
Color4 color;
}VertexData3D;
接下来,这是一个立方体的顶点数据
static GLuint vertexBuffer = 0;
static GLuint indexBuffer = 0;
static VertexData3D vertexArray[24] =
{
// .........................................................................
// < LEFT > face (-X)
{
// Vertex 0
{ -0.5f, +0.5f, -0.5f }, // Position
{ -1.0f, 0.0f, 0.0f }, // Normal (-X)
{ 0.5f/512.0f, 0.5f/512.0f }, // Texture
{ 0xFF, 0xFF, 0xFF, 0xFF} // Color
},
{
// Vertex 1
{ -0.5f, -0.5f, -0.5f }, // Position
{ -1.0f, 0.0f, 0.0f }, // Normal (-X)
{ 0.5f/512.0f, 127.5f/512.0f }, // Texture
{ 0xFF, 0xFF, 0xFF, 0xFF} // Color
},
{
// Vertex 2
{ -0.5f, +0.5f, +0.5f }, // Position
{ -1.0f, 0.0f, 0.0f }, // Normal (-X)
{ 127.5f/512.0f, 0.5f/512.0f }, // Texture
{ 0xFF, 0xFF, 0xFF, 0xFF} // Color
},
{
// Vertex 3
{ -0.5f, -0.5f, +0.5f }, // Position
{ -1.0f, 0.0f, 0.0f }, // Normal (-X)
{ 127.5f/512.0f, 127.5f/512.0f }, // Texture
{ 0xFF, 0xFF, 0xFF, 0xFF} // Color
},
// .........................................................................
// < RIGHT > face (+X)
{
// Vertex 4
{ +0.5f, +0.5f, +0.5f }, // Position
{ +1.0f, 0.0f, 0.0f }, // Normal (+X)
{ 128.5f/512.0f, 0.5f/512.0f }, // Texture
{ 0xFF, 0xFF, 0xFF, 0xFF} // Color
},
{
// Vertex 5
{ +0.5f, -0.5f, +0.5f }, // Position
{ +1.0f, 0.0f, 0.0f }, // Normal (+X)
{ 128.5f/512.0f, 127.5f/512.0f }, // Texture
{ 0xFF, 0xFF, 0xFF, 0xFF} // Color
},
{
// Vertex 6
{ +0.5f, +0.5f, -0.5f }, // Position
{ +1.0f, 0.0f, 0.0f }, // Normal (+X)
{ 255.5f/512.0f, 0.5f/512.0f }, // Texture
{ 0xFF, 0xFF, 0xFF, 0xFF} // Color
},
{
// Vertex 7
{ +0.5f, -0.5f, -0.5f }, // Position
{ +1.0f, 0.0f, 0.0f }, // Normal (+X)
{ 255.5f/512.0f, 127.5f/512.0f }, // Texture
{ 0xFF, 0xFF, 0xFF, 0xFF} // Color
},
// .........................................................................
// < BOTTOM > face (-Y)
{
// Vertex 8
{ -0.5f, -0.5f, +0.5f }, // Position
{ 0.0f, -1.0f, 0.0f }, // Normal (-Y)
{ 0.5f/512.0f, 128.5f/512.0f }, // Texture
{ 0xFF, 0xFF, 0xFF, 0xFF} // Color
},
{
// Vertex 9
{ -0.5f, -0.5f, -0.5f }, // Position
{ 0.0f, -1.0f, 0.0f }, // Normal (-Y)
{ 0.5f/512.0f, 255.5f/512.0f }, // Texture
{ 0xFF, 0xFF, 0xFF, 0xFF} // Color
},
{
// Vertex 10
{ +0.5f, -0.5f, +0.5f }, // Position
{ 0.0f, -1.0f, 0.0f }, // Normal (-Y)
{ 127.5f/512.0f, 128.5f/512.0f }, // Texture
{ 0xFF, 0xFF, 0xFF, 0xFF} // Color
},
{
// Vertex 11
{ +0.5f, -0.5f, -0.5f }, // Position
{ 0.0f, -1.0f, 0.0f }, // Normal (-Y)
{ 127.5f/512.0f, 255.5f/512.0f }, // Texture
{ 0xFF, 0xFF, 0xFF, 0xFF} // Color
},
// .........................................................................
// < TOP > face (+Y)
{
// Vertex 12
{ -0.5f, +0.5f, -0.5f }, // Position
{ 0.0f, +1.0f, 0.0f }, // Normal (+Y)
{ 128.5f/512.0f, 128.5f/512.0f }, // Texture
{ 0xFF, 0xFF, 0xFF, 0xFF} // Color
},
{
// Vertex 13
{ -0.5f, +0.5f, +0.5f }, // Position
{ 0.0f, +1.0f, 0.0f }, // Normal (+Y)
{ 128.5f/512.0f, 255.5f/512.0f }, // Texture
{ 0xFF, 0xFF, 0xFF, 0xFF} // Color
},
{
// Vertex 14
{ +0.5f, +0.5f, -0.5f }, // Position
{ 0.0f, +1.0f, 0.0f }, // Normal (+Y)
{ 255.5f/512.0f, 128.5f/512.0f }, // Texture
{ 0xFF, 0xFF, 0xFF, 0xFF} // Color
},
{
// Vertex 15
{ +0.5f, +0.5f, +0.5f }, // Position
{ 0.0f, +1.0f, 0.0f }, // Normal (-Y)
{ 255.5f/512.0f, 255.5f/512.0f }, // Texture
{ 0xFF, 0xFF, 0xFF, 0xFF} // Color
},
// .........................................................................
// < BACK > face (-Z)
{
// Vertex 16
{ -0.5f, -0.5f, -0.5f }, // Position
{ 0.0f, 0.0f, -1.0f }, // Normal (-Z)
{ 127.5f/512.0f, 383.5f/512.0f }, // Texture
{ 0xFF, 0xFF, 0xFF, 0xFF} // Color
},
{
// Vertex 17
{ -0.5f, +0.5f, -0.5f }, // Position
{ 0.0f, 0.0f, -1.0f }, // Normal (-Z)
{ 127.5f/512.0f, 256.5f/512.0f }, // Texture
{ 0xFF, 0xFF, 0xFF, 0xFF} // Color
},
{
// Vertex 18
{ +0.5f, -0.5f, -0.5f }, // Position
{ 0.0f, 0.0f, -1.0f }, // Normal (-Z)
{ 0.5f/512.0f, 383.5f/512.0f }, // Texture
{ 0xFF, 0xFF, 0xFF, 0xFF} // Color
},
{
// Vertex 19
{ +0.5f, +0.5f, -0.5f }, // Position
{ 0.0f, 0.0f, -1.0f }, // Normal (-Z)
{ 0.5f/512.0f, 256.5f/512.0f }, // Texture
{ 0xFF, 0xFF, 0xFF, 0xFF} // Color
},
// .........................................................................
// < FRONT > face (+Z)
{
// Vertex 20
{ -0.5f, +0.5f, +0.5f }, // Position
{ 0.0f, 0.0f, +1.0f }, // Normal (+Z)
{ 128.5f/512.0f, 256.5f/512.0f }, // Texture
{ 0xFF, 0xFF, 0xFF, 0xFF} // Color
},
{
// Vertex 21
{ -0.5f, -0.5f, +0.5f }, // Position
{ 0.0f, 0.0f, +1.0f }, // Normal (+Z)
{ 128.5f/512.0f, 383.5f/512.0f }, // Texture
{ 0xFF, 0xFF, 0xFF, 0xFF} // Color
},
{
// Vertex 22
{ +0.5f, +0.5f, +0.5f }, // Position
{ 0.0f, 0.0f, +1.0f }, // Normal (+Z)
{ 255.5f/512.0f, 256.5f/512.0f }, // Texture
{ 0xFF, 0xFF, 0xFF, 0xFF} // Color
},
{
// Vertex 23
{ +0.5f, -0.5f, +0.5f }, // Position
{ 0.0f, 0.0f, +1.0f }, // Normal (+Z)
{ 255.5f/512.0f, 383.5f/512.0f }, // Texture
{ 0xFF, 0xFF, 0xFF, 0xFF} // Color
}
};
立方体大小为 1x1x1。您必须提供一个 4x4 模型矩阵(请参阅下面的着色器程序设置)来平移/缩放/旋转您的立方体。数据格式是一个 C 浮点数数组。如何设置,不在此范围内,您可以在互联网上搜索。
纹理坐标假设您使用的是这样的纹理:(每个正方形都是一个面)
...这是索引数据:
static GLushort indexArray[] =
{
// Triangle Strip...
12, // ...
13, // ...
14, // Top Face // CCW
15, // Top Face // CW
22, // Degenerate (14, 15, 22) // (CCW)
20, // Degenarate (15, 22, 20) // (CW)
23, // Front Face (22, 20, 23) // CCW
21, // Front Face (20, 23, 21) // CW
3, // Degenerate (20, 21, 3) // (CCW)
2, // Degenerate (21, 3, 2) // (CW)
1, // Left Face ( 3, 2, 1) // CCW
0, // Left Face ( 2, 1, 0) // CW
16, // Degenerate ( 1, 0, 16) // (CCW)
17, // Degenerate ( 0, 16, 17) // (CW)
18, // Back Face (16, 17, 18) // CCW
19, // Back Face (17, 18, 19) // CW
6, // Degenerate (18, 19, 6) // (CCW)
4, // Degenerate (19, 6, 4) // (CW)
7, // Right Face ( 6, 4, 7) // CCW
5, // Right Face ( 4, 7, 5) // CW
10, // Degenerate ( 7, 5, 10) // (CCW)
8, // Degenerate ( 5, 10, 8) // (CW)
11, // Bottom Face (10, 8, 11) // CCW
9 // Bottom Face ( 8, 11, 9) // CW
};
('CW'表示三角形条带中的顺时针三角形。'CCW'表示逆时针)
这就是我生成 OpenGL 缓冲区的方式:
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, 24*sizeof(VertexData3D), &vertexArray[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glGenBuffers(1, &indexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 24*sizeof(GLushort), &indexArray[0], GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
这些是 OpenGL 参数:(材质、光照等)
static GLfloat lightPosition[4] = { LIGHT_X_POS, LIGHT_Y_POS, LIGHT_Z_POS, 1.0f };
static GLfloat cubeAmbientMaterial[4] = { 0.30f, 0.30f, 0.30f, 1.00f };
static GLfloat cubeDiffuseMaterial[4] = { 0.650f, 0.650f, 0.650f, 1.00f };
static GLfloat cubeSpecularMaterial[4] = { 1.0f, 1.0f, 1.0f, 1.0f};
static GLfloat cubeShininess = 1500.0f;
//Lighting is calculated in MODEL Coordinates:
//Eye and Light Source are located high up along the Z Axis
static GLfloat eyePosition[3] = { 0.0f, 0.0f, CAMERA_Z_POS };
这是抽奖电话:
// VBO Offsets
static GLsizei stride = (GLsizei)(sizeof(VertexData3D));
static GLvoid* positionOffset = (GLvoid*)(0);
static GLvoid* normalOffset = (GLvoid*)(sizeof(Vertex3D));
static GLvoid* textureOffset = (GLvoid*)(2*sizeof(Vertex3D));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBindTexture(GL_TEXTURE_2D, yourTextureID); // Bind your texture
glUseProgram(yourProgram);
// Setup program (Shaders)
glUniformMatrix4fv(viewLocationInProgram, 1, 0, viewMatrix); // Upload the 4x4 view matrix
glUniform3fv(lightPositionLocationInProgram, 1, lightPosition );
glUniform3fv(eyePositionLocationInProgram, 1, eyePosition );
glUniform3fv(ambientMaterialLocationInProgram, 1, cubeAmbientMaterial );
glUniform3fv(specularMaterialLocationInProgram, 1, cubeSpecularMaterial);
glUniform3fv(diffuseMaterialLocationInProgram, 1, cubeDiffuseMaterial );
glUniform1f(shininessLocationInProgram, cubeShininess );
glVertexAttribPointer(positionLocationInProgram, 3, GL_FLOAT, GL_FALSE, stride, positionOffset);
glVertexAttribPointer(normalLocationInProgram, 3, GL_FLOAT, GL_FALSE, stride, normalOffset);
glVertexAttribPointer(texCoordLocationInProgram, 2, GL_FLOAT, GL_FALSE, stride, textureOffset);
glEnableVertexAttribArray(positionLocationInProgram);
glEnableVertexAttribArray(normalLocationInProgram);
glEnableVertexAttribArray(texCoordLocationInProgram);
glUniformMatrix4fv(modelLocationInProgram, 1, 0, modelMatrix);
glUniformMatrix3fv(normalMatrixLocationInProgram, 1, 0, normalMatrix);
glDrawElements(GL_TRIANGLE_STRIP, 48, GL_UNSIGNED_SHORT, 0);
glDrawElements(GL_TRIANGLE_STRIP, 48, GL_UNSIGNED_SHORT, 0);
glDisableVertexAttribArray(positionLocationInProgram);
glDisableVertexAttribArray(normalLocationInProgram);
glDisableVertexAttribArray(texCoordLocationInProgram);
您可以在设置时获得着色器中每个属性/unifoerm 的句柄,使用以下代码:
positionLocationInProgram = glGetAttribLocation(yourProgram, "Position");
normalLocationInProgram = glGetAttribLocation(yourProgram, "Normal");
texCoordLocationInProgram = glGetAttribLocation(yourProgram, "TextureCoord");
modelLocation = glGetUniformLocation(yourProgram, "Model");
viewLocationInProgram = glGetUniformLocation(yourProgram, "View");
normalMatrixLocationInProgram = glGetUniformLocation(yourProgram, "NormalMatrix");
lightPositionLocationInProgram = glGetUniformLocation(yourProgram, "LightPosition");
eyePositionLocationInProgram = glGetUniformLocation(yourProgram, "EyePosition");
ambientMaterialLocationInProgram = glGetUniformLocation(yourProgram, "AmbientMaterial");
diffuseMaterialLocationInProgram = glGetUniformLocation(yourProgram, "DiffuseMaterial");
specularMaterialLocationInProgram = glGetUniformLocation(yourProgram, "SpecularMaterial");
shininessLocationInProgram = glGetUniformLocation(yourProgram, "Shininess");
samplerLocationInProgram = glGetUniformLocation(yourProgram, "Sampler");
glUseProgram(yourProgram);
glUniform1i(samplerLocationInProgram, 0);
(所有以“InProgram”结尾的变量都是 GLints);
最后,顶点着色器:
// These change per-vertex
attribute vec4 Position;
attribute vec3 Normal;
attribute vec2 TextureCoord;
// These change once in a while (e.g., per object)
uniform mat4 Projection;
uniform mat4 Model;
uniform mat4 View;
uniform mat3 NormalMatrix;
uniform vec3 LightPosition;
uniform vec3 EyePosition;
uniform vec3 DiffuseMaterial;
uniform vec3 AmbientMaterial;
uniform vec3 SpecularMaterial;
uniform float Shininess;
// Thes go to the fragment shader (OUTPUT)
varying vec4 DestinationColor;
varying vec2 TextureCoordOut;
void main (void)
{
vec4 P = ( Projection * View * Model ) * Position;
// Position in Model Coordinates
vec3 P2 = vec3( Model * Position );
vec3 N = normalize(NormalMatrix*Normal);
vec3 L = normalize(LightPosition - P2);
vec3 E = normalize(EyePosition - P2);
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 = AmbientMaterial + (df * DiffuseMaterial) + (sf * SpecularMaterial);
DestinationColor = vec4(color, 1);
TextureCoordOut = TextureCoord;
gl_Position = P;
}
...还有片段着色器:
varying lowp vec4 DestinationColor;
varying mediump vec2 TextureCoordOut;
uniform sampler2D Sampler;
void main (void)
{
gl_FragColor = (texture2D(Sampler, TextureCoordOut ) * DestinationColor);
}
请注意这里有很多可能的复杂性,OpenGL 不是一个简单的主题,这段代码可能无法按原样工作,但我相信这是你想要实现的一个很好的起点。我强烈建议你学习这些东西,因为如果你只复制/粘贴别人的代码,就会有很多小事情会出错。