我是 OpenGL 的新手,对此并不了解。我想为UIImageView
添加 3D效果。如何使用OpenGL实现这一目标?我想做一些像这张图片中看到的内容:
我搜索过并发现可以使用OpenGL。我用OpenGL引用了this link。我创建了一个立方体,并且用
取得了一些效果glDrawElements(GL_TRIANGLES, sizeof(Indices)/sizeof(Indices[0]), GL_UNSIGNED_BYTE, 0);
但是我用glDrawRangeElements来了解我们可以创建一个3d立方体,但我不知道如何实现它。
修改
这是我的代码,显示了其中的vertext和索引数组
const Vertex Vertices [] = {
// Front
{{1, -1, 1}, {1, 0, 0, 1}, {1, 0}},
{{1, 1, 1}, {0, 1, 0, 1}, {1, 1}},
{{-1, 1, 1}, {0, 0, 1, 1}, {0, 1}},
{{-1, -1, 1}, {0, 0, 0, 1}, {0, 0}},
// Back
{{1, 1, -1}, {1, 0, 0, 1}, {0, 1}},
{{-1, -1, -1}, {0, 1, 0, 1}, {1, 0}},
{{1, -1, -1}, {0, 0, 1, 1}, {0, 0}},
{{-1, 1, -1}, {0, 0, 0, 1}, {1, 1}},
// Left
{{-1, -1, 1}, {1, 0, 0, 1}, {1, 0}},
{{-1, 1, 1}, {0, 1, 0, 1}, {1, 1}},
{{-1, 1, -1}, {0, 0, 1, 1}, {0, 1}},
{{-1, -1, -1}, {0, 0, 0, 1}, {0, 0}},
// Right
{{1, -1, -1}, {1, 0, 0, 1}, {1, 0}},
{{1, 1, -1}, {0, 1, 0, 1}, {1, 1}},
{{1, 1, 1}, {0, 0, 1, 1}, {0, 1}},
{{1, -1, 1}, {0, 0, 0, 1}, {0, 0}},
// Top
{{1, 1, 1}, {1, 0, 0, 1}, {1, 0}},
{{1, 1, -1}, {0, 1, 0, 1}, {1, 1}},
{{-1, 1, -1}, {0, 0, 1, 1}, {0, 1}},
{{-1, 1, 1}, {0, 0, 0, 1}, {0, 0}},
// Bottom
{{1, -1, -1}, {1, 0, 0, 1}, {1, 0}},
{{1, -1, 1}, {0, 1, 0, 1}, {1, 1}},
{{-1, -1, 1}, {0, 0, 1, 1}, {0, 1}},
{{-1, -1, -1}, {0, 0, 0, 1}, {0, 0}}
};
const GLubyte Indices [] = {
// Front
0, 1, 2,
2, 3, 0,
// Back
4, 6, 5,
4, 5, 7,
// Left
8, 9, 10,
10, 11, 8,
// Right
12, 13, 14,
14, 15, 12,
// Top
16, 17, 18,
18, 19, 16,
// Bottom
20, 21, 22,
22, 23, 20
};
所以请建议我。如果可以使用Core Graphics做更好的工作,那也没关系。
请帮我解决问题。 提前致谢!
答案 0 :(得分:6)
忘记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);
您可以在设置中的着色器 ONCE 中获取每个属性/ 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;
}
......和FRAGMENT着色器:
varying lowp vec4 DestinationColor;
varying mediump vec2 TextureCoordOut;
uniform sampler2D Sampler;
void main (void)
{
gl_FragColor = (texture2D(Sampler, TextureCoordOut ) * DestinationColor);
}
请请注意,这里有很多可能的错综复杂,OpenGL不是一个微不足道的主题,这个代码可能无法正常工作,但我相信这是一个很好的开始指出你想要达到的目标。我认真地建议你学习这些东西,因为如果你只复制/粘贴其他人的代码,就有很多小问题可能会出错。