Domanda

Come faccio rendo sprite 2D in OpenGL dato che ho un png dello sprite? Vedere le immagini come un esempio degli effetti che vorrei realizzare. Inoltre vorrei per sovrapporre le armi sullo schermo, come il fucile nell'immagine in basso. Qualcuno sa come mi avrebbe raggiunto i due effetti? Qualsiasi aiuto è molto apprezzato.

alt text

alt text

È stato utile?

Soluzione

In 3D termini, questo è chiamato un "cartellone". Un cartellone è piano 2D completamente piana con una trama su di esso e si affaccia sempre la telecamera.

Vedi qui per un'implementazione OpenGL pura: http: // Nehe. gamedev.net/data/articles/article.asp?article=19

Quasi ogni motore 3D dovrebbe essere in grado di fare loro per impostazione predefinita. Ogre3D può farlo, per esempio.

Altri suggerimenti

a) Per il primo caso:

Questo non è davvero 2D sprite. Quegli uomini sembrano essere reso come singoli quad con una texture con un qualche tipo di trasparenza (sia alpha test o alpha blending).

In ogni caso, anche un singolo quad può ancora essere considerato un oggetto 3D, quindi per tale situazione si potrebbe desiderare di trattarlo come uno:. Monitorare la sua traslazione e rotazione e renderlo allo stesso modo di qualsiasi altro oggetto 3D

b) Per il secondo caso:

Se si desidera che la pistola (una foto in 2D, ho pressume) da rendere nello stesso luogo senza alcuna trasformazione prospettica, quindi è possibile utilizzare la stessa tecnica si usa per disegnare l'interfaccia grafica (ecc). Date un'occhiata al mio post qui:

2D sovrapposizione su un 3D scena

Per la sovrapposizione dell'arma 2D, è possibile utilizzare glOrtho per la vista della telecamera.

È possibile creare un quad 3d e mappa la texture .png a base ad esso. È possibile effettuare la faccia quad qualsiasi direzione desiderata, come nella prima immagine, o renderlo sempre di fronte alla telecamera (come un cartellone pubblicitario, citato da Svenstaro) come nella vostra seconda foto. Anche se, ad essere onesti, sono sicuro che la seconda foto appena blitted l'immagine (con qualche ridimensionamento) direttamente nel framebuffer software creato (che assomiglia Wolf3d tech, il rendering software).

Date un'occhiata a OpenGL Point Sprites:

http://www.informit.com/articles/article. aspx? p = 770.639 & seqNum = 7

Particolarmente utile per i sistemi di partical, ma può fare il trucco per i vostri scopi.

Controlla questo tutorial su cartelloni pubblicitari. Penso che troverete utile. http://www.lighthouse3d.com/opengl/billboarding/

OpenGL dimostrativi ha:

Cattura schermo:

entrare descrizione dell'immagine qui

Codice:

#include <stdio.h>
#include <stdlib.h>

#include <vector>
#include <algorithm>

#include <GL/glew.h>

#include <glfw3.h>
GLFWwindow* window;

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/norm.hpp>
using namespace glm;


#include <common/shader.hpp>
#include <common/texture.hpp>
#include <common/controls.hpp>

#define DRAW_CUBE // Comment or uncomment this to simplify the code

int main( void )
{
    // Initialise GLFW
    if( !glfwInit() )
    {
        fprintf( stderr, "Failed to initialize GLFW\n" );
        getchar();
        return -1;
    }

    glfwWindowHint(GLFW_SAMPLES, 4);
    glfwWindowHint(GLFW_RESIZABLE,GL_FALSE);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // To make MacOS happy; should not be needed
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    // Open a window and create its OpenGL context
    window = glfwCreateWindow( 1024, 768, "Tutorial 18 - Billboards", NULL, NULL);
    if( window == NULL ){
        fprintf( stderr, "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 version of the tutorials.\n" );
        getchar();
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);

    // Initialize GLEW
    glewExperimental = true; // Needed for core profile
    if (glewInit() != GLEW_OK) {
        fprintf(stderr, "Failed to initialize GLEW\n");
        getchar();
        glfwTerminate();
        return -1;
    }

    // Ensure we can capture the escape key being pressed below
    glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
    // Hide the mouse and enable unlimited mouvement
    glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);

    // Set the mouse at the center of the screen
    glfwPollEvents();
    glfwSetCursorPos(window, 1024/2, 768/2);

    // Dark blue background
    glClearColor(0.0f, 0.0f, 0.4f, 0.0f);

    // Enable depth test
    glEnable(GL_DEPTH_TEST);
    // Accept fragment if it closer to the camera than the former one
    glDepthFunc(GL_LESS);

    GLuint VertexArrayID;
    glGenVertexArrays(1, &VertexArrayID);
    glBindVertexArray(VertexArrayID);


    // Create and compile our GLSL program from the shaders
    GLuint programID = LoadShaders( "Billboard.vertexshader", "Billboard.fragmentshader" );

    // Vertex shader
    GLuint CameraRight_worldspace_ID  = glGetUniformLocation(programID, "CameraRight_worldspace");
    GLuint CameraUp_worldspace_ID  = glGetUniformLocation(programID, "CameraUp_worldspace");
    GLuint ViewProjMatrixID = glGetUniformLocation(programID, "VP");
    GLuint BillboardPosID = glGetUniformLocation(programID, "BillboardPos");
    GLuint BillboardSizeID = glGetUniformLocation(programID, "BillboardSize");
    GLuint LifeLevelID = glGetUniformLocation(programID, "LifeLevel");

    GLuint TextureID  = glGetUniformLocation(programID, "myTextureSampler");


    GLuint Texture = loadDDS("ExampleBillboard.DDS");

    // The VBO containing the 4 vertices of the particles.
    static const GLfloat g_vertex_buffer_data[] = { 
         -0.5f, -0.5f, 0.0f,
          0.5f, -0.5f, 0.0f,
         -0.5f,  0.5f, 0.0f,
          0.5f,  0.5f, 0.0f,
    };
    GLuint billboard_vertex_buffer;
    glGenBuffers(1, &billboard_vertex_buffer);
    glBindBuffer(GL_ARRAY_BUFFER, billboard_vertex_buffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_DYNAMIC_DRAW);

#ifdef DRAW_CUBE
    // Everything here comes from Tutorial 4
    GLuint cubeProgramID = LoadShaders( "../tutorial04_colored_cube/TransformVertexShader.vertexshader", "../tutorial04_colored_cube/ColorFragmentShader.fragmentshader" );
    GLuint cubeMatrixID = glGetUniformLocation(cubeProgramID, "MVP");
    static const GLfloat g_cube_vertex_buffer_data[] = { -1.0f,-1.0f,-1.0f,-1.0f,-1.0f, 1.0f,-1.0f, 1.0f, 1.0f,1.0f, 1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f, 1.0f,-1.0f,1.0f,-1.0f, 1.0f,-1.0f,-1.0f,-1.0f,1.0f,-1.0f,-1.0f,1.0f, 1.0f,-1.0f,1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f, 1.0f, 1.0f,-1.0f, 1.0f,-1.0f,1.0f,-1.0f, 1.0f,-1.0f,-1.0f, 1.0f,-1.0f,-1.0f,-1.0f,-1.0f, 1.0f, 1.0f,-1.0f,-1.0f, 1.0f,1.0f,-1.0f, 1.0f,1.0f, 1.0f, 1.0f,1.0f,-1.0f,-1.0f,1.0f, 1.0f,-1.0f,1.0f,-1.0f,-1.0f,1.0f, 1.0f, 1.0f,1.0f,-1.0f, 1.0f,1.0f, 1.0f, 1.0f,1.0f, 1.0f,-1.0f,-1.0f, 1.0f,-1.0f,1.0f, 1.0f, 1.0f,-1.0f, 1.0f,-1.0f,-1.0f, 1.0f, 1.0f,1.0f, 1.0f, 1.0f,-1.0f, 1.0f, 1.0f,1.0f,-1.0f, 1.0f};
    static const GLfloat g_cube_color_buffer_data[] = { 0.583f,  0.771f,  0.014f,0.609f,  0.115f,  0.436f,0.327f,  0.483f,  0.844f,0.822f,  0.569f,  0.201f,0.435f,  0.602f,  0.223f,0.310f,  0.747f,  0.185f,0.597f,  0.770f,  0.761f,0.559f,  0.436f,  0.730f,0.359f,  0.583f,  0.152f,0.483f,  0.596f,  0.789f,0.559f,  0.861f,  0.639f,0.195f,  0.548f,  0.859f,0.014f,  0.184f,  0.576f,0.771f,  0.328f,  0.970f,0.406f,  0.615f,  0.116f,0.676f,  0.977f,  0.133f,0.971f,  0.572f,  0.833f,0.140f,  0.616f,  0.489f,0.997f,  0.513f,  0.064f,0.945f,  0.719f,  0.592f,0.543f,  0.021f,  0.978f,0.279f,  0.317f,  0.505f,0.167f,  0.620f,  0.077f,0.347f,  0.857f,  0.137f,0.055f,  0.953f,  0.042f,0.714f,  0.505f,  0.345f,0.783f,  0.290f,  0.734f,0.722f,  0.645f,  0.174f,0.302f,  0.455f,  0.848f,0.225f,  0.587f,  0.040f,0.517f,  0.713f,  0.338f,0.053f,  0.959f,  0.120f,0.393f,  0.621f,  0.362f,0.673f,  0.211f,  0.457f,0.820f,  0.883f,  0.371f,0.982f,  0.099f,  0.879f};
    GLuint cubevertexbuffer;
    glGenBuffers(1, &cubevertexbuffer);
    glBindBuffer(GL_ARRAY_BUFFER, cubevertexbuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(g_cube_vertex_buffer_data), g_cube_vertex_buffer_data, GL_DYNAMIC_DRAW);
    GLuint cubecolorbuffer;
    glGenBuffers(1, &cubecolorbuffer);
    glBindBuffer(GL_ARRAY_BUFFER, cubecolorbuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(g_cube_color_buffer_data), g_cube_color_buffer_data, GL_DYNAMIC_DRAW);
#endif

    double lastTime = glfwGetTime();
    do
    {
        // Clear the screen
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        double currentTime = glfwGetTime();
        double delta = currentTime - lastTime;
        lastTime = currentTime;


        computeMatricesFromInputs();
        glm::mat4 ProjectionMatrix = getProjectionMatrix();
        glm::mat4 ViewMatrix = getViewMatrix();



#ifdef DRAW_CUBE
        // Again : this is just Tutorial 4 !
        glDisable(GL_BLEND);
        glUseProgram(cubeProgramID);
        glm::mat4 cubeModelMatrix(1.0f);
        cubeModelMatrix = glm::scale(cubeModelMatrix, glm::vec3(0.2f, 0.2f, 0.2f));
        glm::mat4 cubeMVP = ProjectionMatrix * ViewMatrix * cubeModelMatrix;
        glUniformMatrix4fv(cubeMatrixID, 1, GL_FALSE, &cubeMVP[0][0]);
        glEnableVertexAttribArray(0);
        glBindBuffer(GL_ARRAY_BUFFER, cubevertexbuffer);
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0  );
        glEnableVertexAttribArray(1);
        glBindBuffer(GL_ARRAY_BUFFER, cubecolorbuffer);
        glVertexAttribPointer(1, 3, GL_FLOAT,  GL_FALSE, 0, (void*)0   );
        glDrawArrays(GL_TRIANGLES, 0, 12*3);
        glDisableVertexAttribArray(0);
        glDisableVertexAttribArray(1);
#endif



        // We will need the camera's position in order to sort the particles
        // w.r.t the camera's distance.
        // There should be a getCameraPosition() function in common/controls.cpp, 
        // but this works too.
        glm::vec3 CameraPosition(glm::inverse(ViewMatrix)[3]);

        glm::mat4 ViewProjectionMatrix = ProjectionMatrix * ViewMatrix;





        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

        // Use our shader
        glUseProgram(programID);

        // Bind our texture in Texture Unit 0
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, Texture);
        // Set our "myTextureSampler" sampler to user Texture Unit 0
        glUniform1i(TextureID, 0);

        // This is the only interesting part of the tutorial.
        // This is equivalent to mlutiplying (1,0,0) and (0,1,0) by inverse(ViewMatrix).
        // ViewMatrix is orthogonal (it was made this way), 
        // so its inverse is also its transpose, 
        // and transposing a matrix is "free" (inversing is slooow)
        glUniform3f(CameraRight_worldspace_ID, ViewMatrix[0][0], ViewMatrix[1][0], ViewMatrix[2][0]);
        glUniform3f(CameraUp_worldspace_ID   , ViewMatrix[0][1], ViewMatrix[1][1], ViewMatrix[2][1]);

        glUniform3f(BillboardPosID, 0.0f, 0.5f, 0.0f); // The billboard will be just above the cube
        glUniform2f(BillboardSizeID, 1.0f, 0.125f);     // and 1m*12cm, because it matches its 256*32 resolution =)

        // Generate some fake life level and send it to glsl
        float LifeLevel = sin(currentTime)*0.1f + 0.7f;
        glUniform1f(LifeLevelID, LifeLevel);

        glUniformMatrix4fv(ViewProjMatrixID, 1, GL_FALSE, &ViewProjectionMatrix[0][0]);

        // 1rst attribute buffer : vertices
        glEnableVertexAttribArray(0);
        glBindBuffer(GL_ARRAY_BUFFER, billboard_vertex_buffer);
        glVertexAttribPointer(
            0,                  // attribute. No particular reason for 0, but must match the layout in the shader.
            3,                  // size
            GL_FLOAT,           // type
            GL_FALSE,           // normalized?
            0,                  // stride
            (void*)0            // array buffer offset
        );


        // Draw the billboard !
        // This draws a triangle_strip which looks like a quad.
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

        glDisableVertexAttribArray(0);


        // Swap buffers
        glfwSwapBuffers(window);
        glfwPollEvents();

    } // Check if the ESC key was pressed or the window was closed
    while( glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS &&
           glfwWindowShouldClose(window) == 0 );


    // Cleanup VBO and shader
    glDeleteBuffers(1, &billboard_vertex_buffer);
    glDeleteProgram(programID);
    glDeleteTextures(1, &TextureID);
    glDeleteVertexArrays(1, &VertexArrayID);
#ifdef DRAW_CUBE
    glDeleteProgram(cubeProgramID);
    glDeleteVertexArrays(1, &cubevertexbuffer);
    glDeleteVertexArrays(1, &cubecolorbuffer);
#endif
    // Close OpenGL window and terminate GLFW
    glfwTerminate();

    return 0;
}

testato su Ubuntu 15.10.

https:

Axis versione di questa domanda orientata // gamedev.stackexchange.com/questions/35946/how-do-i-implement-camera-axis-aligned-billboards Qui abbiamo fatto un punto di vista orientato cartellone.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top