如何使用OpenGL为UIImageView / uiview提供3D效果看起来像3D立方体

时间:2012-07-07 12:57:02

标签: iphone opengl-es uiimageview core-graphics

我是 OpenGL 的新手,对此并不了解。我想为UIImageView添加 3D效果。如何使用OpenGL实现这一目标?我想做一些像这张图片中看到的内容:enter image description here

我搜索过并发现可以使用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做更好的工作,那也没关系。

请帮我解决问题。 提前致谢!

1 个答案:

答案 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数组。如何设置,超出了范围,您可以在互联网上搜索。

纹理坐标假设您正在使用这样的纹理:(每个正方形是一个面)

enter image description here

...这是索引数据:

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不是一个微不足道的主题,这个代码可能无法正常工作,但我相信这是一个很好的开始指出你想要达到的目标。我认真地建议你学习这些东西,因为如果你只复制/粘贴其他人的代码,就有很多小问题可能会出错。