如何为这个球体添加纹理?

Posted

技术标签:

【中文标题】如何为这个球体添加纹理?【英文标题】:How to add texture to this sphere? 【发布时间】:2020-04-16 13:27:56 【问题描述】:

我创建了一个旋转的有线球体。我已经为立方体做了纹理,但球体似乎是个问题。 我想将世界地图作为纹理添加到这个球体。有什么建议吗?

#include <iostream>
#include <stdlib.h>
#include <GL/glut.h>
#include <thread>
#include <chrono>
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
using namespace std;
GLuint texture;
int start = 1;
GLfloat xRotated, yRotated, zRotated;
GLdouble radius = 1;
void init() 
    glOrtho(-1000 / 2, 1000 / 2, -1000 / 2, 1000 / 2, -500, 500);



GLuint glInitTexture(char* filename)

    GLuint t = 0;
    int width, height, nrChannels;
    stbi_set_flip_vertically_on_load(true);
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    unsigned char* data = stbi_load(filename, &width, &height, &nrChannels, 0);

    glGenTextures(1, &t);
    glBindTexture(GL_TEXTURE_2D, t);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
    //unsigned char data[] =  255, 0, 0, 255 ;
    if (data)
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
    else
        std::cout << "fail";
    return t;




void drawImage(GLuint file, float x, float y, float w, float h)


    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
    glPushMatrix();
    //glTranslatef(x, y, 0.0);
    //glRotatef(angle, 0.0, 0.0, 1.0);
    //glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glBindTexture(GL_TEXTURE_2D, file);

    glEnable(GL_TEXTURE_2D);
    glClear(GL_COLOR_BUFFER_BIT);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glTranslatef(0.0, 0.0, -4.5);

    glRotatef(yRotated, 0.0, 1.0, 0.0);

    glEnable(GL_TEXTURE_2D);
    GLUquadric *qobj = gluNewQuadric();
    gluQuadricTexture(qobj, GL_TRUE);
    gluSphere(qobj, radius, 20, 20);
    gluDeleteQuadric(qobj);
    glDisable(GL_TEXTURE_2D);

    glFlush();

    yRotated += 0.01;
    //glBindTexture(GL_TEXTURE_2D, 0);
    glFlush();
    glPopMatrix();
    glDisable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, 0);




//Plots points of both graphs together


//Displays map on screen
void drawMap() 
    std::cout << "\nDraw map\n";

    glMatrixMode(GL_PROJECTION);

    glLoadIdentity();
    const double w = glutGet(GLUT_WINDOW_WIDTH);
    const double h = glutGet(GLUT_WINDOW_HEIGHT);
    gluPerspective(90.0, w / h, 0.1, 1000.0);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glTranslatef(0, 0, -15);

    for (int i = 0; i < 10000; i++) 
        glClear(GL_DEPTH_BUFFER_BIT);
        drawImage(texture, 0, 0, 100, 200);
        //std::this_thread::sleep_for(std::chrono::milliseconds(500));
    
    glutSwapBuffers();
    glEnd();
    glFlush();


void render()







    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);


    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glEnable(GL_DEPTH_TEST);



    //glFlush();


    glPointSize(5);
    glColor3f(1, 1, 1);
    glBegin(GL_LINES);
    glVertex3f(-450, -450, 10);
    glVertex3f(-450, -250, 10);
    glEnd();
    glBegin(GL_LINES);
    glVertex3f(-450, -450, 10);
    glVertex3f(-250, -450, 10);

    glEnd();






    drawMap();

    //plotPoints();
    glFlush();




void Kbevent(unsigned char key, int x, int y) 
    if (key == 's') 
        start = start % 2;
        glutPostRedisplay();
    



int main(int argc, char* argv[])

    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(1560, 810);
    glutCreateWindow("Applying Textures");
    init();
    xRotated = yRotated = zRotated = 30.0;
    xRotated = 33;
    yRotated = 40;


    char fn[] = "map.jpg";
    texture = glInitTexture(fn);
    glutDisplayFunc(render);
    //glutReshapeFunc(reshapeFunc);
    //glutIdleFunc(idleFunc);
    glutKeyboardFunc(Kbevent);
    glutMainLoop();

    return 0;


应用 2D 纹理的问题在于,当您将 2D 纹理包裹到球体上时,球体的顶部和底部区域会显得纹理被挤压。

【问题讨论】:

使用gluSphere 而不是glutSolidSphere 见Applying map of the earth texture a Sphere,甚至可能是Bump-map a sphere with a texture map 【参考方案1】:

我建议使用gluSpheregluQuadricTexture 而不是glutSolidSphere。例如:

glEnable(GL_TEXTURE_2D);

GLUquadric *qobj = gluNewQuadric();
gluQuadricTexture(qobj, GL_TRUE);
gluSphere(qobj, radius, 20, 20);
gluDeleteQuadric(qobj);

glDisable(GL_TEXTURE_2D);

对于连续旋转,您需要增加旋转角度并不断更新窗口 (glutPostRedisplay)。例如:

void redisplayFunc(void)

    glClear(GL_COLOR_BUFFER_BIT);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glTranslatef(0.0, 0.0, -4.5);

    glRotatef(yRotated, 0.0, 1.0, 0.0);

    glEnable(GL_TEXTURE_2D);
    GLUquadric *qobj = gluNewQuadric();
    gluQuadricTexture(qobj, GL_TRUE);
    gluSphere(qobj, radius, 20, 20);
    gluDeleteQuadric(qobj);
    glDisable(GL_TEXTURE_2D);

    glFlush();

    yRotated += 1;
    glutPostRedisplay();

【讨论】:

谢谢!!我现在要做的就是轮换 @ShreyasB 我已经扩展了答案。

以上是关于如何为这个球体添加纹理?的主要内容,如果未能解决你的问题,请参考以下文章

使用索引时如何为 UV 添加 vec2 以进行纹理映射

Android OpenGL添加纹理

OpenGL VBO球体纹理加载不起作用

球体在使用纹理渲染时显示多边形

OpenGL 半球纹理映射

如何纹理球体的不规则平面?