问题描述
我是 OpenGL 的新手,对它了解不多.我想向UIImageView
添加 3D效果.如何使用OpenGL实现此目的?我想做类似此图中所示的操作:
I am new to OpenGL and don't much have knowledge in it. I want to add a 3D effect to a UIImageView
. How can I achieve this using OpenGL? I want to do something like seen in this image:
我搜索并发现可以使用OpenGL.我已经使用OpenGL引用了此链接.我创建了一个多维数据集,并对
I have searched and found that it is possible using OpenGL. I have referred to this link With OpenGL . I have created a cube, and got some effect with
glDrawElements(GL_TRIANGLES, sizeof(Indices)/sizeof(Indices[0]), GL_UNSIGNED_BYTE, 0);
但是我通过 glDrawRangeElements 知道了制作一个3D立方体,但是我不知道如何实现相同的功能.
But I come to know with glDrawRangeElements we can make a 3d cube, But I do not have idea how to implement the same.
编辑
这是我的代码,显示文本和索引数组
Here is my code showing ther vertext and indices array
const Vertex Vertices [] = {
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索引[] = {
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做一些更好的工作,那就还可以.
So please suggest me . If it is possible to do some better work with Core Graphics , then also fine.
请帮助我获得解决方案.提前致谢!
Please help me to get the solution.Thanks in Advance!
推荐答案
忘记UIImage/etc.如果要使用OpenGL在3D中渲染多维数据集,则必须使用OpenGL纹理对其进行纹理映射.这是OpenGL中所有非常基本的东西.网络上肯定有很多关于1.纹理贴图和2.绘制立方体的教程.
Forget about UIImage/etc. If you are rendering a cube in 3D with OpenGL, you must texture-map it using an OpenGL texture. This is all pretty basic stuff in OpenGL; there must be like a ton of tutorials on the web about 1. Texture mapping and 2. Drawing a Cube.
确保搜索"OpenGL ES 1.1","OpenGL ES 2.0"或"GLKit"
Make sure to search for "OpenGL ES 1.1", "OpenGL ES 2.0", OR "GLKit"
编辑试试这个: http://www.raywenderlich.com/4404/opengl-es-2-0-for-iphone-tutorial-part-2-textures
编辑2
好的,一些源代码.首先,我使用这种顶点数据格式:
OK, some source code.First, I use this vertex data format:
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;
接下来,这是一个立方体的顶点数据
Next, this is the vertex data for one cube
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数组.如何设置它,不在这里讨论的范围,您可以在Internet上搜索它.
Cube size is 1x1x1. You must provide a 4x4 Model matrix (see shader program setup below) to translate/scale/rotate your cube. The data format is a C array of floats. How to set it up, is beyond the scope here and you can search it in the internet.
纹理坐标假定您使用的是这样的纹理:(每个正方形都是一个面)
Texture coordinates assume you are using a texture like this: (each square is a face)
...这是索引数据:
...and this is the Index Data:
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"表示逆时针)
('CW' denotes a Clockwise triangle in the triangle strip. 'CCW' denotes Counter-clockwise)
这是我生成OpenGL缓冲区的方式:
This is how I generate the OpenGL buffers:
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参数:(材质,照明等)
These are the OpenGL parameters: (material, lighting, etc.)
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的句柄:
You get the handles to each attribute/unifoerm in the shader ONCE on setup, with this code:
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);
(All variables that end in 'InProgram' are 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着色器:
...And the FRAGMENT shader:
varying lowp vec4 DestinationColor;
varying mediump vec2 TextureCoordOut;
uniform sampler2D Sampler;
void main (void)
{
gl_FragColor = (texture2D(Sampler, TextureCoordOut ) * DestinationColor);
}
请请注意,这里有很多可能的复杂性,OpenGL并不是一个琐碎的主题,该代码可能无法正常工作,但我相信这是一个很好的开始指向您想要实现的目标.我强烈建议您学习这些知识,因为如果您仅复制/粘贴其他人的代码,那么会有很多小事情会出错.
Please note that there are lots of possible intricacies here, OpenGL is not a trivial subject, this code may not work as is, but I believe it's a good starting point for what you want to achieve. I seriously recommend you learn this stuff, because there is a ton of little things that can go wrong if you only copy/paste somebody else's code.
这篇关于如何使用OpenGL将3D效果赋予UIImageView/uiview看起来像是3D CUBE的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!