Текстурирование нескольких объектов с различными текстурами

Может ли кто-нибудь объяснить мне, как я могу рендерить несколько объектов с разными текстурами в OpenGL?

Я думаю, что я почти до конечного результата, но в данный момент я застрял здесь, и я не знаю, что мне нужно делать дальше. Действительно нужна помощь!

На данный момент вот что у меня есть:

  1. drawSphere (): нарисовать УФ-сферу на основе количества длин и лат

    int numberOfVerices = 0;

    for(int i = 0; i <= lats; i++) {
    double lat0 = M_PI * (-0.5 + (double) (i - 1) / lats);
    double z0  = sin(lat0);
    double zr0 =  cos(lat0);
    
    double lat1 = M_PI * (-0.5 + (double) i / lats);
    double z1 = sin(lat1);
    double zr1 = cos(lat1);
    
    for(int j = 0; j <= longs; j++) {
    double lng = 2 * M_PI * (double) (j - 1) / longs;
    double x = cos(lng);
    double y = sin(lng);
    
    glNormal3f(x * zr0, y * zr0, z0);
    
    vertices.push_back(x * zr0);
    vertices.push_back(y * zr0);
    vertices.push_back(z0);
    indices.push_back(numberOfVerices);
    numberOfVerices++;
    
    vertices.push_back(x * zr1);
    vertices.push_back(y * zr1);
    vertices.push_back(z1);
    indices.push_back(numberOfVerices);
    numberOfVerices++;
    }
    indices.push_back(GL_PRIMITIVE_RESTART_FIXED_INDEX);
    }
    
  2. SetupGeometry (): этот метод используется для привязки вершин и координат текстуры.

DrawSphere (300, 300);

glGenBuffers(1, &vboVertex);
glBindBuffer(GL_ARRAY_BUFFER, vboVertex);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(GLfloat), &vertices[0], GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(0);

glGenBuffers(1, &vboTexture);
glBindBuffer(GL_ARRAY_BUFFER, vboTexture);
glBufferData(GL_ARRAY_BUFFER, texture.size() * sizeof(GLfloat), &texture[0], GL_STATIC_DRAW);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(1);

glGenBuffers(1, &vboIndex);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndex);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLuint), &indices[0], GL_STATIC_DRAW);

numsToDraw = indices.size();
nums = indices.size();
  1. SetupShader (): создать шейдер и скомпилировать шейдер

текст char [1000];
длина int;

vertexSource = filetobuf("space/sphere.vert");
fragmentSource = filetobuf("space/sphere.frag");

vertexShader = glCreateShader(GL_VERTEX_SHADER);
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);

glShaderSource(vertexShader, 1, (const GLchar**) &vertexSource, 0);
glShaderSource(fragmentShader, 1, (const GLchar**) &fragmentSource, 0);

fprintf(stderr, "Compiling vertex shader....\n");
glCompileShader(vertexShader);
fprintf(stderr, "Compiling fragment shader....\n");
glCompileShader(fragmentShader);
fprintf(stderr, "Done....\n");

shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);

glBindAttribLocation(shaderProgram, 0, "in_Position");
glBindAttribLocation(shaderProgram, 1, "Texture_Coord");

printf("Linking program ... \n");
glLinkProgram(shaderProgram);

glGetProgramInfoLog(shaderProgram, 1000, &length, text);
if(length > 0){
fprintf(stderr, "Validate Shader Program\n%s\n", text );
}

glUseProgram(shaderProgram);
  1. SetupTexture (char * filename): загрузка изображения, генерирование 2 массивов текстур, один для GL_TEXTURE0, а другой для GL_TEXTURE1

GLuint texture [2];
glGenTextures (2, текстура);

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture[0]);
data = stbi_load(fileName, &w, &h, &n, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glUniform1i(glGetUniformLocation(shaderProgram, "texture_Sun"), 0);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
stbi_image_free(data);

glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture[1]);
data = stbi_load(fileName1, &w, &h, &n, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glUniform1i(glGetUniformLocation(shaderProgram, "texture_Earth"), 1);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
stbi_image_free(data);
  1. Render (int i): рендеринг 2 объектов, то есть сферы.

glClearColor (0.0, 0.0, 0.0, 1.0); / * сделать наш фон черным * /
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glEnable(GL_PRIMITIVE_RESTART);
glPrimitiveRestartIndex(GL_PRIMITIVE_RESTART_FIXED_INDEX);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndex);

glPushMatrix();
glLoadIdentity();
glm::mat4 Projection = glm::perspective(50.0f, 5.0f / 3.0f, 1.0f, 100.0f);
glm::mat4 View = glm::lookAt(
glm::vec3(0, 5, 2),
glm::vec3(0, 0, 0),
glm::vec3(0, 1, 0)
);

/* Animations */
GLfloat angle = (GLfloat) (i);
View = glm::translate(View, glm::vec3(2.0f, 0.0f, 0.0f));
View = glm::rotate(View, angle * 0.5f, glm::vec3(0.0f, 0.0f, 1.0f));
/* ******* */

glm::mat4 Model = glm::mat4(1.0f);
glm::mat4 MVP = Projection * View * Model;

glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "mvpMatrix"), 1, GL_FALSE, glm::value_ptr(MVP));
glDrawElements(GL_QUAD_STRIP, numsToDraw, GL_UNSIGNED_INT, NULL);
glPopMatrix();

glPushMatrix();
glLoadIdentity();
glm::mat4 Projection1 = glm::perspective(50.0f, 5.0f / 3.0f, 1.0f, 100.0f);
glm::mat4 View1 = glm::lookAt(
glm::vec3(0, 5, 2),
glm::vec3(0, 0, 0),
glm::vec3(0, 1, 0)
);

/* Animations */
GLfloat angle1 = (GLfloat) (i);
View1 = glm::translate(View1, glm::vec3(-2.0f, 0.0f, 0.0f));
View1 = glm::rotate(View1, angle1 * -0.5f, glm::vec3(0.0f, 0.0f, 1.0f));
/* ******* */

glm::mat4 Model1 = glm::mat4(1.0f);
MVP = Projection1 * View1 * Model1;

glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "mvpMatrix"), 1, GL_FALSE, glm::value_ptr(MVP));
glDrawElements(GL_QUAD_STRIP, nums, GL_UNSIGNED_INT, NULL);
glPopMatrix();

VertexShader:

#version 330 core
precision highp float;
attribute vec3 in_Position;
attribute vec3 in_Position1;
varying vec4 Texture_Coord;

uniform mat4 mvpMatrix;

void main(void){
gl_Position = mvpMatrix * vec4(in_Position, 1.0);
Texture_Coord = vec4(in_Position, 1.0);
}

FragmentShader:

#version 330 core
precision highp float;
varying vec4 Texture_Coord;

uniform sampler2D texture_Sun;
uniform sampler2D texture_Earth;

out vec4 FragColor;

void main(void){
vec2 longLat = vec2((atan(Texture_Coord.y, Texture_Coord.x)/3.1415926 + 1) * 0.5, (asin(Texture_Coord.z) / 3.1415926 + 0.5));

FragColor = texture2D(texture_Sun, longLat);
FragColor = texture2D(texture_Earth, longLat);
}

Основные коды в основном:

SetupGeomtry();
SetupShader();
SetupTexture("images/Earth.jpg", "images/sun.jpg");
/*
*  Main loop
*/
int i = 0;
while(!glfwWindowShouldClose(window)){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

Render(i+=1);
glfwSwapBuffers(window);
glfwPollEvents();
Sleep(10);
}

1

Решение

Обычно вы загружаете ваши текстуры (т.е. буферизуете их в GPU):

GLuint texture[2];
glGenTextures(2, texture);

glBindTexture(GL_TEXTURE_2D, texture[0]);
data = stbi_load(fileName, &w, &h, &n, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
stbi_image_free(data);

glBindTexture(GL_TEXTURE_2D, texture[1]);
data = stbi_load(fileName1, &w, &h, &n, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
stbi_image_free(data);

затем перед рисованием каждого из ваших объектов свяжите соответствующую текстуру для указанного объекта:

// already selected the shader programme for both Sun and Earth
GLint textureLocation = glGetUniformLocation(shaderProgram, "texture_CelestialBody");
// optionally remember more locations for multi texture

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture[0]);
glUniform1i(textureLocation, 0);
// optionally bind more textures for multi texture shader...
// draw Sun now

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture[1]);
glUniform1i(textureLocation, 0);
// optionally bind more textures for multi texture shader...
// draw Earth now

тогда texture_CelestialBody идентифицирует текстуру как для Солнца, так и для Земли — то есть фрагментный шейдер не будет различать их.

1

Другие решения


По вопросам рекламы [email protected]