@KazukiSamuel

Как возможно задать параметры, а именно текстуру отдельно для каждого треугольника?

Есть у меня модель в которой отдельно хранится координаты вершин и индексный буфер вместе с ID текстуры, модель не разделена на отдельные части по текстуре. И вот вопрос в том, как накладывать текстуру отдельно на каждый треугольник ? Через текстурный атлас не получится, ибо текстуры разные по размерам.

Код

// Std. Includes
#include <iostream>
#include <map>
#include <string>
#include <vector>
// GLEW
#define GLEW_STATIC
#include <GL/glew.h>
// GLFW
#include <GLFW/glfw3.h>
// GLM
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/string_cast.hpp>
#include <glm/gtc/type_ptr.hpp>

// GL includes
#include "Shader.h"
#include "Texture.h"
#define DEBUG
#include "Model.h"

static uint32_t WIDTH = 900;
static uint32_t HEIGHT = 700;


void processInput(GLFWwindow *window)
{
	if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
		glfwSetWindowShouldClose(window, true);
}


void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
	glViewport(0, 0, width, height);
}



int main()
{
	glfwInit();
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

	GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "TestProgram", NULL, NULL);
	if (window == NULL)
	{
		std::cout << "Failed to create GLFW window" << std::endl;
		glfwTerminate();
		return -1;
	}
	glfwMakeContextCurrent(window);
	glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);

	glewExperimental = true;
	glewInit();


	Shader shader = Shader("shaders/text.vert", "shaders/text.frag");

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


	//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
	float vertices[] = {
		1.0f, 1.0f, 0.0f,	1.0f, 1.0f, 0.0f, 1.0f, // top right
		1.0f, 0.0f, 0.0f,	1.0f, 0.0f,  1.0f, 1.0f, // bottom right
		0.0f, 0.0f, 0.0f,	0.0f, 0.0f,  1.0f, 1.0f, // bottom left
		0.0f, 1.0f, 0.0f,	0.0f, 1.0f,  1.0f, 1.0f, // top left 
	};
	uint32_t indices[] = {
		0, 1, 3,   // first triangle
		1, 2, 3    // second triangle
	};
	uint32_t VBO = 0;
	uint32_t VAO = 0;
	uint32_t EBO = 0;
#pragma pack(push, 1)
	struct Vec2
	{
		float x;
		float y;
	};
	struct Vertex {

		mod::Vector3 pos;
		Vec2 uv;
		Vec2 dat;
	};
	struct Index {
		uint32_t a;
		uint32_t b;
		uint32_t c;
	};
#pragma pack(pop)


	std::vector<Vertex> data = {
		//{ 1.0f, 1.0f, 0.0f,	1.0f, 1.0f, 0.0f, 1.0f }, // top right
		//{ 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f }, // bottom right
		//{ 0.0f, 0.0f, 0.0f,	0.0f, 0.0f, 1.0f, 1.0f }, // bottom left
		//{ 0.0f, 1.0f, 0.0f,	0.0f, 1.0f, 1.0f, 1.0f }, // top left 
	};
	std::vector<Index> index = {
		//{ 0, 1, 3 },
		//{ 1, 2, 3 }
	};

	mod::Frame* mod = mod::Model::_()->loadModel("model.of");
	std::cout << "(I)Name: " << mod->name << std::endl;

	mod::Geometry m = *(mod->geom);
	for (int i = 0; i < m.header.vertice_count; i++) {
		mod::Vector3 v = m.vertexs[i];
		data.push_back({ v, 1.0f, 1.0f, 1.0f, 1.0f });
	}

	for (int i = 0; i < m.header.triangle_count; i++) {
		mod::Triangle t = m.triangles[i];
		index.push_back({ t.index_a, t.index_b, t.index_c });
		t.print();
	}

	glGenVertexArrays(1, &VAO);
	glGenBuffers(1, &VBO);
	glGenBuffers(1, &EBO);

	glBindVertexArray(VAO);

	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	glBufferData(GL_ARRAY_BUFFER, data.size() * sizeof(Vertex), &data[0], GL_STATIC_DRAW);

	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, index.size() * sizeof(Index), &index[0], GL_STATIC_DRAW);

	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 7 * sizeof(float), (void*)0);
	glEnableVertexAttribArray(0);

	glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 7 * sizeof(float), (void*)(3 * sizeof(float)));
	glEnableVertexAttribArray(1);

	glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 7 * sizeof(float), (void*)(5 * sizeof(float)));
	glEnableVertexAttribArray(2);
	

	glm::mat4 projection = glm::perspective(glm::radians(45.0f), (float)WIDTH / (float)HEIGHT, 0.1f, 100.0f);
	glm::mat4 view = glm::lookAt(glm::vec3(0.0f, 2.0f, 5.0f),
		glm::vec3(0.0f, 0.0f, 0.0f),
		glm::vec3(0.0f, 1.0f, 0.0f));
	glm::mat4 model = glm::mat4(1.0f);

	Texture* texture = new Texture("image.jpg");
	Texture* texture1 = new Texture("image1.jpg");

	while (!glfwWindowShouldClose(window))
	{

		processInput(window);

		glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
		glClear(GL_COLOR_BUFFER_BIT);

		shader.use();
		shader.setMat4("projection", projection);
		shader.setMat4("view", view);
		shader.setMat4("model", model);

		shader.setInt("texture1", 0);
		glActiveTexture(GL_TEXTURE0);
		glBindTexture(GL_TEXTURE_2D, texture->ID());

		shader.setInt("texture2", 1);
		glActiveTexture(GL_TEXTURE1);
		glBindTexture(GL_TEXTURE_2D, texture1->ID());
		
		glBindVertexArray(VAO); 
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
		glDrawElements(GL_TRIANGLES, 3*8, GL_UNSIGNED_INT, 0);

		glfwSwapBuffers(window);
		glfwPollEvents();
	}
	glfwTerminate();
	return 0;
}


#version 330 core
out vec4 FragColor;

in vec2 TexCoord;
in vec2 test;


uniform sampler2D texture1;
uniform sampler2D texture2;

void main()
{
	if(test.x == 1.0)
		FragColor = texture(texture1, TexCoord);
	else
		FragColor = texture(texture2, TexCoord);
}


#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoord;
layout (location = 2) in vec2 aTest;

out vec2 TexCoord;
out vec2 test;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main()
{
	gl_Position = projection * view * model * vec4(aPos, 1.0f);
	TexCoord = aTexCoord;
	test = aTest;
}

vertice_count: 9
triangle_count: 8
  • Вопрос задан
  • 92 просмотра
Решения вопроса 2
gbg
@gbg Куратор тега C++
Любые ответы на любые вопросы
Назначаете разные текстурные координаты разным граням - и готово.
Ответ написан
@MarkusD Куратор тега C++
все время мелю чепуху :)
Коротко, тебе нужно усвоить вот этот урок.

Развернуто:

У тебя из атрибутов вершины сейчас есть только позиция. Уникальных вершин для твоей плоскости в таком случае будет всего 4. Под уникальностью у вершины понимается уникальность комбинации всех ее атрибутов.

Сейчас тебе надо добавить атрибуты текстурных координат. Так как смешивание тебя не интересует, тебе необходим всего один набор текстурных координат на вершину. В таком случае уникальность твоей вершины будет обусловлена уже не просто ее позицией, но еще и уникальностью набора текстурных координат. Одновременно с этим новым правилом уникальности для вершины вводится и еще одно правило уникальности: уникальность по материалу.
Когда ты добавляешь одну лишь текстуру, чтобы твоя отрисовка не встала на костыли тебе нужно поднять целую инфраструктуру обеспечения правильности ее работы.

Под материалом понимается комплекс из программы и ресурсов, которые отображаются на геометрии.
Материал отображает на геометрию заданный своими свойствами набор текстур и параметров. С точки зрения геометрии, материал - это DIP (Draw Indexed Primitive - твой glDrawElements). С точки зрения шейдера, материал - это комплекс из программы шейдера и набора входных/выходных параметров этой программы.
Один материал одной геометрии - это один DIP с установкой набора текстур и параметров материала, а так же - с установкой нужного буфера индексов, вершин и инстансов.

Ты хочешь чтобы Один набор треугольников твоей плоскости имел одну текстуру, а другой - другую. Вот и организуй два материала, у которых одна шейдерная программа, но две разные текстуры. Далее тебе надо ввести больше вершин, т.к. с вводом материала и текстурных координат, с учетом твоих требований, твои 4 вершины больше не могут обеспечить свою уникальность. В тех позициях плоскости, где два смежных треугольника отображают разные текстуры, тебе требуется ввести по две вершины вместо одной.
Далее - организуй индексный буфер так, чтобы примитивы в нем описывались непрерывной последовательностью для каждого материала отдельно. Т.е. сперва все треугольники с одним материалом, потом все треугольники - с другим.
Под конец определи инструкции для своей геометрии, сколько DIP-ов согласно твоим требованиям должно быть выполнено, для каких материалов и на какой геометрии.

Таким образом ты реализуешь очень простую систему поддержки материалов и выполнишь свою задачу.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы