MVP matrixy wariują open gl

0

Cześć! Próbuję zrobić efekt kostki i na razie zatrzymałem się na przechylaniu tekstury, bo problem polega na tym, że gdy odpalam aplikację tekstura zaczyna wariować
tak wygląda while loop

		glm::mat4 model;
		model = glm::rotate(model, glm::radians(-55.0f), glm::vec3(1.0, 0.0, 0.0));

		glm::mat4 view;
		view = glm::translate(view, glm::vec3(0.0f, 0.0f, -3.0f));

		glm::mat4 projection;
		projection = glm::perspective(glm::radians(45.0f), 1280.0f / 720.0f, 0.1f, 100.0f);

		// Od razu przypisuje uniform do programu shadera
		GLint u_model = shader.GetUniformLocation("u_model");
		GLint u_view = shader.GetUniformLocation("u_view");
		GLint u_projection = shader.GetUniformLocation("u_projection");

		glUniformMatrix4fv(u_model, 1, GL_FALSE, glm::value_ptr(model));
		glUniformMatrix4fv(u_view, 1, GL_FALSE, glm::value_ptr(view));
		glUniformMatrix4fv(u_projection, 1, GL_FALSE, glm::value_ptr(projection));

		Rect destRect = { -0.5, -0.5, 1.0, 1.0 };
		Rect uvRect = { 0.0f, 0.0f, 1.0f, 1.0f };

		texture.Draw(destRect, uvRect);

		window.SwapWindow();
#version 330 core

layout (location = 0) in vec3 a_position;
layout (location = 1) in vec4 a_color;
layout (location = 2) in vec2 a_uv;

out vec2 v_UV;
out vec4 v_Color;
out vec2 v_Position;

uniform mat4 u_model;
uniform mat4 u_view;
uniform mat4 u_projection;

void main()
{
	gl_Position = u_projection * u_view * u_model * vec4(a_position, 1.0);
	
	v_Position = a_position;
	v_Color = a_color;
	v_UV = vec2(a_uv.x, 1 - a_uv.y);
}

Takie właśnie wygibasy

Zrobiłem sobie klasę kamery (do gry 2D) i przy glm::ortho wszystko gra i buczy, a jak próbuje wejść w 3d to takie nienormalne rzeczy się robią.

W jaki sposób to naprawić?

0
    gl_Position = u_projection * u_view * u_model * vec4(a_position, 1.0);

Nie potrzebujesz trzech macierzy, wystarczą dwie: projection i modelview.
Pokaż fragment shader.

0

Nie za bardzo rozumiem.
Mam zrobić coś takiego:

	glm::mat4 model;
		model = glm::rotate(model, glm::radians(-55.0f), glm::vec3(1.0, 0.0, 0.0));

		model = glm::translate(model, glm::vec3(0.0f, 0.0f, -3.0f));

		glm::mat4 projection;
		projection = glm::perspective(glm::radians(45.0f), 1280.0f / 720.0f, 0.1f, 100.0f);

		GLint u_model = shader.GetUniformLocation("u_model");
		GLint u_projection = shader.GetUniformLocation("u_projection");

		glUniformMatrix4fv(u_model, 1, GL_FALSE, glm::value_ptr(model));
		glUniformMatrix4fv(u_projection, 1, GL_FALSE, glm::value_ptr(projection));
uniform mat4 u_model;
uniform mat4 u_projection;

void main()
{
	gl_Position = u_projection * u_model * vec4(a_position, 0.0, 1.0);

?
Nadal niczego to nie zmienia :c

0
#version 330 core

out vec4 outColor;

in vec2 v_UV;
in vec4 v_Color;
in vec2 v_Position;

uniform sampler2D u_textureSampler;

void main()
{
	vec4 textureColor = texture(u_textureSampler, v_UV);
	outColor = v_Color * textureColor;
}
Quad::Quad(const Rect & destRect, const Rect & uvRect, GLuint Texture, const Color &color) :
		texture(Texture)
	{
		topLeft.color = color;
		topLeft.setPosition(destRect.x, destRect.y + destRect.h);
		topLeft.setUV(uvRect.x, uvRect.y + uvRect.h);

		bottomLeft.color = color;
		bottomLeft.setPosition(destRect.x, destRect.y);
		bottomLeft.setUV(uvRect.x, uvRect.y);

		bottomRight.color = color;
		bottomRight.setPosition(destRect.x + destRect.w, destRect.y);
		bottomRight.setUV(uvRect.x + uvRect.w, uvRect.y);

		topRight.color = color;
		topRight.setPosition(destRect.x + destRect.w, destRect.y + destRect.h);
		topRight.setUV(uvRect.x + uvRect.w, uvRect.y + uvRect.h);
	}
	void Sprite::Draw(const Rect &destRect, const Rect &uvRect, GLuint texture, const Color &color)
	{
		quad.emplace_back(destRect, uvRect, texture, color);
	}

	void Sprite::Render()
	{
		glBindVertexArray(vao);
		for (const auto & ren : render) {
			glEnable(GL_CULL_FACE);
			glCullFace(GL_FRONT);
			glFrontFace(GL_CW);

			glBindTexture(GL_TEXTURE_2D, ren.texture);
			glDrawArrays(GL_TRIANGLES, ren.offset, ren.numVertices);
		}
		glBindVertexArray(0);
		glBindTexture(GL_TEXTURE_2D, 0);
	}

	void SpriteBatch::Begin(SortType sort)
	{
		glActiveTexture(GL_TEXTURE0);
		sortType = sort;
		render.clear();
		quadPointers.clear();
		quad.clear();
	}

	void SpriteBatch::End()
	{
		quadPointers.resize(quad.size());
		for (size_t i = 0; i < quad.size(); i++) {
			quadPointers[i] = &quad[i];
		}
		Sort();
		CreateRenderBatches();
	}


void Texture::Draw(const Rect &destRect, const Rect &uvRect, const Color &color)
{
        sprite.Begin();
	sprite.Draw(destRect, uvRect, color);
	sprite.End();
	sprite.Render();
}

Tutaj raczej wszystko powinno być dobrze, bo bez tych macierzy i innych wygibasów tekstura ładuje się dobrze. Kiedy zmieniałem z tych openglowskich coordów na normalne (tzn. te które mamy w bibliotekach takich jak sfml czy sdl) to też działało.

Wtedy zrobiłem sobie u_CameraMatrix i pomnożyłem u_CameraMatrix * pozycja w shaderze i gitara.

0

W tym kodzie nie potrzebujesz trzech macierzy, ale mogą zostać, masz od razu bazę do zrobienia kamery, chociaż view powinien być stowarzyszony z funkcją glm::lookAt, bo nie wiem jak się zachowa z funkcją glm::translate (dobra pomyłka, normalnie, najpierw mnożenie rotate potem translate, więc normalnie), więc view ustaw sobie na razie na identity (macierz jednostkową) a te translate przypisz do model, pamiętaj że kolejność ma znaczenie, obrót i przestawienie może wyglądać inaczej niż przestawienie i obrót, podejrzewam że chodzi o tę drugą kombinację.

Zbindowałeś shader przed ustawieniem uniformów? (glUseProgram(shaderID).

Ustaw model i view na macierz jednostkową przed dokonaniem operacji:

glm::mat4 model = glm::mat4();
model = glm::translate(model, glm::vec3(0.0f, 0.0f, -3.0f));

"Kiedy zmieniałem z tych openglowskich coordów na normalne" - masz na myśli glm::vec3 etc.?

0

masz na myśli glm::vec3 etc.?

Nie, chodzi mi o to, że dzięki ortho matrixie, pewnie o tym wiesz, można uzyskać inne osie. Open gl przyjmuje je od -1.0 do 1.0 (to są chyba normal deviced coordinates, ale nie jestem pewien czy to tak sie nazywa), a zmieniam je na x = 0, y = 0, w = 1280, h = 720, tzn. dest rect obrazka moge ustawić sobie np.

glm::vec4(1280/2, 720/2, 1280, 720);

i będzie on wtedy mniej więcej na środku ekranu, zamiast robić

glm::vec4(-0.5, -0.5, 1.0, 1.0);

I wtedy jak zrobie taką "konwersje" to wszystko działa miód malina, a jak chce zrobić właśnie z tym przechyleniem: przechylenie.png

to obrazek wariuje tak jak na pokazanym filmiku albo teraz jak ustawiłem ten identity macierz to się nic nie pokazuje, nawet te wariacje

		glm::mat4 model = glm::mat4();
		model = glm::rotate(model, glm::radians(-55.0f), glm::vec3(1.0, 0.0, 0.0));

		model = glm::translate(model, glm::vec3(0.0f, 0.0f, -3.0f));

		glm::mat4 projection = glm::mat4();
		projection = glm::perspective(glm::radians(45.0f), 1280.0f / 720.0f, 0.1f, 100.0f);

		GLint u_model = shader.GetUniformLocation("u_model");
		GLint u_projection = shader.GetUniformLocation("u_projection");

		glUniformMatrix4fv(u_model, 1, GL_FALSE, glm::value_ptr(model));
		glUniformMatrix4fv(u_projection, 1, GL_FALSE, glm::value_ptr(projection));

Zbindowałeś shader przed ustawieniem uniformów?

Oczywiście. Chyba, że musze to zrobić jeszcze w game loopie ale właśnie sprawdzam i też nie działa.

0

Zrób najpierw translate, potem rotate, bo teraz masz tak, że obracasz układ współrzędnych o dany kąt potem go przesuwasz, a chcesz pewnie obrócić obrazek i go oddalić, więc powinieneś pomnożyć macierze w odwrotnej kolejności.

model = glm::translate(model, glm::vec3(0.0f, 0.0f, -3.0f));
model = glm::rotate(model, glm::radians(-55.0f), glm::vec3(1.0, 0.0, 0.0));

Te wywołania translate i rotate masz w gamie loopie?

0

Zrób najpierw translate, potem rotate, bo teraz masz tak, że obracasz układ współrzędnych o dany kąt potem go przesuwasz, a chcesz pewnie obrócić obrazek i go oddalić, więc powinieneś pomnożyć macierze w odwrotnej kolejności.

Chyba mniej kolizyjnie jest zrobienie 3 macierzy. Zrobiłem tak jak mówisz i nadal to samo.

Te wywołania translate i rotate masz w gamie loopie?

tak mam w loopie

0

To dlatego ci wariowało

model = glm::rotate(model, glm::radians(-55.0f), glm::vec3(1.0, 0.0, 0.0));

za każdym obrotem pętli wartość model się cały czas zmieniała w efekcie co obrót kąt był coraz większy.
Perspective nie musisz zerować, nie ma w tej funkcji zależności od poprzedniej wartości, a w zasadzie możesz ustawić tę wartość raz przed pętlą.

Ale czemu teraz nic ci nie pokazuje nie mam zielonego pojęcia.

0

Nadal nic

0

pokaż cały kod

0

main

int main(int argc, char*args[])
{
	MainGame mainGame;
	mainGame.GameLoop();

	return 0;
}

MainGame::MainGame()
{
	//Tworzy okno - nazwa, w, h, parametr, vsync
	window.CreateWindow("openGL", 1280, 720, SDL_WINDOW_OPENGL, true);

	texture.Initialize();
	texture.LoadFromFile("image.png");

	std::string vertex = shader.LoadFromFile("vertex.shader");
	std::string fragment = shader.LoadFromFile("fragment.shader");

	shader.CreateShaderProgram();
	shader.CreateShaders(vertex.c_str(), fragment.c_str());
	shader.UseShaderProgram();

	GLint u_textureSampler = shader.GetUniformLocation("u_textureSampler");
	glUniform1f(u_textureSampler, 0);

	glClearColor(0.0f, 0.0f, 0.0f, 255.0f);
}

void MainGame::GameLoop()
{
	while (!quit) 
	{
		while (SDL_PollEvent(&event)) 
		{
			if (event.type == SDL_QUIT) 
			{
				SDL_Quit();
				exit(0);
			}
		}

		glClearDepth(1.0f);
		glEnable(GL_DEPTH_TEST);  
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

		glm::mat4 model;

		model = glm::translate(model, glm::vec3(0.0f, 0.0f, -3.0f));
		model = glm::rotate(model, glm::radians(-55.0f), glm::vec3(1.0, 0.0, 0.0));

		glm::mat4 projection;
		projection = glm::perspective(glm::radians(45.0f), 1280.0f / 720.0f, 0.1f, 100.0f);

		GLint u_model = shader.GetUniformLocation("u_model");
		GLint u_projection = shader.GetUniformLocation("u_projection");

		glUniformMatrix4fv(u_model, 1, GL_FALSE, glm::value_ptr(model));
		glUniformMatrix4fv(u_projection, 1, GL_FALSE, glm::value_ptr(projection));

		Rect destRect = { -0.5, -0.5, 1.0, 1.0 };
		Rect uvRect = { 0.0f, 0.0f, 1.0f, 1.0f };

		texture.Begin();
		texture.Draw(destRect, uvRect);
		texture.End();
		texture.Render();

		window.Swap();
	}
}

Texture

	Texture::Texture() {}

	Texture::~Texture() {}

	void Texture::Initialize()
	{
		sprite.CreateVertexArray();
	}

	void Texture::LoadFromFile(const std::string &filePath)
	{
		texture = textureCache.getTexture(filePath);

		w = textureCache.getWidth();
		h = textureCache.getHeight();
	}

	void Texture::Begin()
	{
		sprite.Begin();
	}

	void Texture::Draw(Rect destRect, Rect uvRect, ColorRGBA8 color)
	{
		glActiveTexture(GL_TEXTURE0);
		sprite.Draw(destRect, uvRect, texture, color);
	}

	void Texture::End()
	{
		sprite.End();
	}

	void Texture::Render()
	{
		sprite.Render();
	}

	void Texture::DrawBDER(Rect destRect, Rect uvRect, ColorRGBA8 color)
	{
		Begin();
		Draw(destRect, uvRect, color);
		End();
		Render();
	}

	int Texture::getWidth()
	{
		return w;
	}

	int Texture::getHeight()
	{
		return h;
	}

//----------------------------------------------------------------------------------------------------------------

	TextureCache::TextureCache() :
		w(0), h(0)
	{}

	TextureCache::~TextureCache() { textureMap.clear(); }

	GLuint TextureCache::LoadFromFile(const std::string & filePath)
	{
		textureMap.clear();

		GLuint texture = 0;

		SDL_Surface* surface = IMG_Load(filePath.c_str());

		glGenTextures(1, &texture);
		glBindTexture(GL_TEXTURE_2D, texture);

		int Format;
		if(surface->format->BytesPerPixel == 4) {
			Format = GL_RGBA;
		} else {
			Format = GL_RGB;
		}
		w = surface->w;
		h = surface->h;

		glTexImage2D(GL_TEXTURE_2D, 0, Format, w, h, 0, Format, GL_UNSIGNED_BYTE, surface->pixels);

		SDL_FreeSurface(surface);

		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);

		glGenerateMipmap(GL_TEXTURE_2D);

		glBindTexture(GL_TEXTURE_2D, 0);

		return texture;
	}
	
	GLuint TextureCache::getTexture(const std::string &filePath)
	{
		auto mit = textureMap.find(filePath);

		if (mit == textureMap.end()) 
		{
			GLuint newTexture = LoadFromFile(filePath);

			textureMap[filePath] = newTexture;

			return newTexture;
		}
		return mit->second;
	}

	int TextureCache::getWidth()
	{
		return w;
	}

	int TextureCache::getHeight()
	{
		return h;
	}

Sprite.h

enum class SortType
	{
		NONE, FRONT_TO_BACK, BACK_TO_FRONT, TEXTURE
	};

	class Glyph
	{
	public:
		Glyph() {}
		Glyph(const Rect &destRect, const Rect &uvRect, GLuint Texture, const ColorRGBA8 &color = { 255, 255, 255, 255 });

		GLuint texture;
		float depth;

		Vertex topLeft;
		Vertex topRight;
		Vertex bottomLeft;
		Vertex bottomRight;
	};

	class RenderBatch
	{
	public:
		RenderBatch(GLuint Offset, GLuint NumVertices, GLuint Texture) :
			offset(Offset), numVertices(NumVertices), texture(Texture)
		{}
		~RenderBatch() {}

		GLuint offset;
		GLuint numVertices;
		GLuint texture;
	};
	
	class Sprite
	{
	public:
		Sprite();
		~Sprite();

		void CreateVertexArray();
		void Free();

		void Begin(SortType sort = SortType::TEXTURE);
		void Draw(const Rect &destRect, const Rect &uvRect, GLuint texture, const ColorRGBA8 &color);
		void End();
		void Render();
	private:
		void CreateRenderBatches();
		GLuint vbo;
		GLuint vao;
		GLuint ebo;		

		void Sort();
		static bool compereFrontToBack(Glyph *a, Glyph *b);
		static bool compereBackToFront(Glyph *a, Glyph *b);
		static bool compereTexture(Glyph *a, Glyph *b);

		std::vector<Glyph> glyphs; // Actual glyphs
		std::vector<Glyph*> glyphPointers; // For sorting
		std::vector<RenderBatch> renderBatches;

		SortType sortType;
	};

sprite.h


	Glyph::Glyph(const Rect & destRect, const Rect & uvRect, GLuint Texture, const ColorRGBA8 &color) :
		texture(Texture)
	{
		topLeft.color = color;
		topLeft.setPosition(destRect.x, destRect.y + destRect.h);
		topLeft.setUV(uvRect.x, uvRect.y + uvRect.h);

		bottomLeft.color = color;
		bottomLeft.setPosition(destRect.x, destRect.y);
		bottomLeft.setUV(uvRect.x, uvRect.y);

		bottomRight.color = color;
		bottomRight.setPosition(destRect.x + destRect.w, destRect.y);
		bottomRight.setUV(uvRect.x + uvRect.w, uvRect.y);

		topRight.color = color;
		topRight.setPosition(destRect.x + destRect.w, destRect.y + destRect.h);
		topRight.setUV(uvRect.x + uvRect.w, uvRect.y + uvRect.h);
	}

Sprite::Sprite() : vbo(0), vao(0), ebo(0)
	{}

	Sprite::~Sprite() { Free(); }

	void Sprite::Free()
	{
		glDeleteBuffers(1, &vbo);
		glDeleteBuffers(1, &ebo);
		glDeleteVertexArrays(1, &vao);

		renderBatches.clear();

		for (const auto & gp : glyphPointers) {
			delete gp;
		}
		glyphPointers.clear();

		glyphs.clear();
	}

	void Sprite::Begin(SortType sort)
	{
		glActiveTexture(GL_TEXTURE0);
		sortType = sort;
		renderBatches.clear();
		glyphPointers.clear();
		glyphs.clear();
	}

	void Sprite::End()
	{
		glyphPointers.resize(glyphs.size());
		for (size_t i = 0; i < glyphs.size(); i++) 
		{
			glyphPointers[i] = &glyphs[i];
		}
		Sort();
		CreateRenderBatches();
	}

	void Sprite::Draw(const Rect &destRect, const Rect &uvRect, GLuint texture, const ColorRGBA8 &color)
	{
		glyphs.emplace_back(destRect, uvRect, texture, color);
	}

	void Sprite::Render()
	{
		glBindVertexArray(vao);
		for (const auto & rb : renderBatches) 
		{
			//glEnable(GL_CULL_FACE);
			//glCullFace(GL_FRONT);
			//glFrontFace(GL_CW);

			glBindTexture(GL_TEXTURE_2D, rb.texture);
			glDrawArrays(GL_TRIANGLES, rb.offset, rb.numVertices);
		}
		glBindVertexArray(0);
		glBindTexture(GL_TEXTURE_2D, 0);
	}

	void Sprite::CreateRenderBatches()
	{
		std::vector<Vertex> verticies;
		verticies.resize(glyphPointers.size() * 6);
		if (glyphPointers.empty()) return;

		int offset = 0;
		int cv = 0; // current vertex;

		renderBatches.emplace_back(offset, 6, glyphPointers[0]->texture);
		verticies[cv++] = glyphPointers[0]->topLeft;
		verticies[cv++] = glyphPointers[0]->bottomLeft;
		verticies[cv++] = glyphPointers[0]->bottomRight;
		verticies[cv++] = glyphPointers[0]->bottomRight;
		verticies[cv++] = glyphPointers[0]->topRight;
		verticies[cv++] = glyphPointers[0]->topLeft;
		offset += 6;

		for (int i = 1; i < glyphPointers.size(); i++) 
		{
			if (glyphPointers[i]->texture != glyphPointers[i - 1]->texture)
			 {
				renderBatches.emplace_back(offset, 6, glyphPointers[i]->texture);
			} 
			else 
			{
				renderBatches.back().numVertices += 6;
			}

			verticies[cv++] = glyphPointers[i]->topLeft;
			verticies[cv++] = glyphPointers[i]->bottomLeft;
			verticies[cv++] = glyphPointers[i]->bottomRight;
			verticies[cv++] = glyphPointers[i]->bottomRight;
			verticies[cv++] = glyphPointers[i]->topRight;
			verticies[cv++] = glyphPointers[i]->topLeft;
			offset += 6;
		}

		glBindBuffer(GL_ARRAY_BUFFER, vbo);
		glBufferData(GL_ARRAY_BUFFER, verticies.size() * sizeof(Vertex), nullptr, GL_DYNAMIC_DRAW);
		glBufferSubData(GL_ARRAY_BUFFER, 0, verticies.size() * sizeof(Vertex), verticies.data());

		glBindBuffer(GL_ARRAY_BUFFER, 0);
	}

	void Sprite::CreateVertexArray()
	{
		glGenVertexArrays(1, &vao);
		glBindVertexArray(vao);

		glGenBuffers(1, &vbo);
		glBindBuffer(GL_ARRAY_BUFFER, vbo);

		glGenBuffers(1, &ebo);
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);

		glEnableVertexAttribArray(0);
		glEnableVertexAttribArray(1);
		glEnableVertexAttribArray(2);

		glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, position));
		glVertexAttribPointer(1, 4, GL_FLOAT, GL_TRUE, sizeof(Vertex), (void*)offsetof(Vertex, color));
		glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, uv));

		glBindVertexArray(0);
	}

	void Sprite::Sort()
	{
		switch (sortType)
		{
			case SortType::BACK_TO_FRONT: std::stable_sort(glyphPointers.begin(), glyphPointers.end(), compereBackToFront); break;
			case SortType::FRONT_TO_BACK: std::stable_sort(glyphPointers.begin(), glyphPointers.end(), compereFrontToBack); break;
			case SortType::TEXTURE:       std::stable_sort(glyphPointers.begin(), glyphPointers.end(), compereTexture);     break;
		}
	}

	bool Sprite::compereFrontToBack(Glyph* a, Glyph* b)
	{
		return a->depth < b->depth;
	}

	bool Sprite::compereBackToFront(Glyph* a, Glyph* b)
	{
		return a->depth > b->depth;
	}

	bool Sprite::compereTexture(Glyph* a, Glyph* b)
	{
		return a->texture < b->texture;
	}

Teraz jestem w trakcie zmieniania z samych vertexów na index buffer object, stąd te kawałki dodatkowego kodu.

0

Dziwny podział na klasy, tekstura powinna być raczej składową sprite'a a nie na odwrót. Nie wiem po co jest textura i textureCache, wystarczy jedna klasa tekstura w której załadujesz obrazek i przechowasz zmienne w i h (w zasadzie to tylko nazewnictwo czasami, ale dziwnie się czyta).

Trochę mało to wszystko czytelne, spróbuj jeszcze raz jakoś czytelniej rozpisać, mały przykład: https://pastebin.com/1kFLwk0K (może nie taki mały, bo się bawiłem stencil bufferem żeby uzyskać efekt lustra).

Co do tego czemu nie działa nie mogę się doszukać.

1
czaffik napisał(a):

za każdym obrotem pętli wartość model się cały czas zmieniała w efekcie co obrót kąt był coraz większy.

W tym kodzie w ogóle jest dużo rzeczy niepotrzebnie wykonywanych wielokrotnie. Choć to raczej nie zaszkodzi, po prostu zmniejsza wydajność – nawet jeśli nie w przypadku prostej sceny, warto mieć nawyk unikania powtarzania tych samych komend:

           glEnable(GL_CULL_FACE);
           glCullFace(GL_FRONT);
           glFrontFace(GL_CW);

— nie ma powodu by to wywoływać dla każdego rysowanego obiektu. Jeśli nigdy nie zmieniasz tych parametrów, wystarczy raz przy inicjalizacji.

       glBindVertexArray(0);
       glBindTexture(GL_TEXTURE_2D, 0);

— odbindowywanie VAO i tekstury niczemu właściwie nie służy. VAO – jeśli używasz tylko jednego – wystarczy zabindować raz, przy inicjalizacji. Teksturę tylko gdy zmieniasz.

Pamiętaj że OpenGL to maszyna stanów. glEnable na czymś wykonane raz zachowuje ważność aż nie zostanie zmienione. Nie trzeba całego stanu odnawiać przy każdym obiekcie czy nawet przy każdej rysowanej klatce.

       glClearDepth(1.0f);
       glEnable(GL_DEPTH_TEST);  

— j.w.

       glActiveTexture(GL_TEXTURE0);

— jeśli nie używasz multiteksturowania to w ogóle nie potrzebujesz glActiveTexture. Jeśli używasz wielu tekstur na raz, to może być potrzebne do ustawiania parametrów tych tekstur, ale nie do rysowania.

        GLint u_model = shader.GetUniformLocation("u_model");
        GLint u_projection = shader.GetUniformLocation("u_projection");

— to też powinno być w części inicjalizacyjnej, nie w pętli rysującej.

0
GLint u_model = shader.GetUniformLocation("u_model");
 GLint u_projection = shader.GetUniformLocation("u_projection");

— to też powinno być w części inicjalizacyjnej, nie w pętli rysującej.

Dobrze wiedziec. W poradniku bylo w petli

glActiveTexture(GL_TEXTURE0);

— jeśli nie używasz multiteksturowania to w ogóle nie potrzebujesz glActiveTexture. Jeśli używasz wielu tekstur na raz, to może być potrzebne do ustawiania parametrów tych tekstur, ale nie do rysowania.

Jestem tego swiadomy.

glBindVertexArray(0);
glBindTexture(GL_TEXTURE_2D, 0);

— odbindowywanie VAO i tekstury niczemu właściwie nie służy. VAO – jeśli używasz tylko jednego – wystarczy zabindować raz, przy inicjalizacji. Teksturę tylko gdy zmieniasz.

czyli z metody render po prostu wyrzucic to

0

Dziwny podział na klasy, tekstura powinna być raczej składową sprite'a a nie na odwrót.

To znaczy?

Nie wiem po co jest textura i textureCache

texture cache jest taką małą klasą w pliku Texture.h. Wygodniej mi się tak nazywa i korzysta po prostu.

Trochę mało to wszystko czytelne

Co dokładnie nie jest czytelne? Klasa Glyph rysuje nam prostokąt, robię tablice pointerów na glyph do sortowania, a bez pointera do prawdziwego prostokąta. Begin wybiera metode sortowania i czyści resztę. End dodaje prawdziwy glyph do pointerów, sortuje i tworzy vertexy i przesyła je do gpu (chyba tak to działa, jestem w tym nowy). Render rysuje obiekt. Nie wiem zbytnio co moze byc mało czytelne. Chociaż może można sie troche zaplątać.

0

Trochę to przekombinowane jak na prosty program typu efekt kostki…
Zacznij może od prostego po prostu narysowania tej kostki.
Do tego wystarczy ci statyczna tablica 8 wierzchołków i glDrawArrays. Potem dodaj teksturę.
Jak to zadziała dopiero wtedy stopniowo baw się w podział na klasy, jakieś render batche, sortowanie itp.
W obecnym kodzie naprawdę trudno dojść dlaczego nie działa – tyle tego jest.

0

@SiemkaElkoTszyPiencZerko: klasa Tekstura u ciebie powinna się raczej nazywać prostokąt albo sprite, tymczasem zawiera w sobie i teksturę (która nazywa się tekstureCache i sprite'a który tworzy siatkę i przekazuje ją do shadera, a wystarczy sama klasa sprite która zawiera w sobie teksturę którą nałożysz na prostokąt, a klasa Glyph całkiem już zaciemnia obraz, pamiętaj że im więcej masz takich podziałów kiedy ich nie potrzeba tym trudniej dojść o co chodzi.

0
Azarien napisał(a):

Trochę to przekombinowane jak na prosty program typu efekt kostki…
Zacznij może od prostego po prostu narysowania tej kostki.
Do tego wystarczy ci statyczna tablica 8 wierzchołków i glDrawArrays. Potem dodaj teksturę.
Jak to zadziała dopiero wtedy stopniowo baw się w podział na klasy, jakieś render batche, sortowanie itp.
W obecnym kodzie naprawdę trudno dojść dlaczego nie działa – tyle tego jest.

To tak właśnie zrobiłem.

struct Rect {
	float x, y;
	float w, h;
};
struct Position {
	float x, y;
};

struct UV {
	float u, v;
};

struct ColorRGBA {
	GLubyte r, g, b, a;
};
class VertexData
{
public:
	VertexData();
	~VertexData();

	void setPosition(float x, float y);
	void setcolor(ColorRGBA color);
	void setUV(float u, float v);

	UV uv;
	ColorRGBA color;
	Position position;
};
#pragma once

#include "VertexData.h"
#include <glew.h>

class Mesh
{
public:
	Mesh();
	~Mesh();
	void CreateVertexArray();

	void CreateQuad(Rect destRect, Rect uvRect, ColorRGBA color);

	void Draw();
private:
	GLuint vao, vbo, ebo;

	VertexData vertex[4];
};
#include "Mesh.h"

Mesh::Mesh(){}

Mesh::~Mesh(){}

void Mesh::CreateVertexArray()
{
	glGenVertexArrays(1, &vao);
	glBindVertexArray(vao);

	glGenBuffers(1, &vbo);
	glBindBuffer(GL_ARRAY_BUFFER, vbo);

	glGenBuffers(1, &ebo);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);

	glEnableVertexAttribArray(0);
	glEnableVertexAttribArray(1);
	glEnableVertexAttribArray(2);

	glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)offsetof(VertexData, position));
	glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)offsetof(VertexData, uv));
	glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(VertexData), (void*)offsetof(VertexData, color));

	glBindVertexArray(0);
}

void Mesh::CreateQuad(Rect destRect, Rect uvRect, ColorRGBA color)
{
	vertex[0].color = color; // topleft
	vertex[0].setPosition(destRect.x, destRect.y + destRect.h);
	vertex[0].setUV(uvRect.x, uvRect.y + uvRect.h);

	vertex[1].color = color;
	vertex[1].setPosition(destRect.x, destRect.y); // bottom left
	vertex[1].setUV(uvRect.x, uvRect.y);

	vertex[2].color = color;
	vertex[2].setPosition(destRect.x + destRect.w, destRect.y); // bottom right
	vertex[2].setUV(uvRect.x + uvRect.w, uvRect.y);

	vertex[3].color = color;
	vertex[3].setPosition(destRect.x + destRect.w, destRect.y + destRect.h); // top right
	vertex[3].setUV(uvRect.x + uvRect.w, uvRect.y + uvRect.h);

	GLuint indices[6] = {
		0, 1, 2,
		2, 3, 0
	};

	glBindBuffer(GL_ARRAY_BUFFER, vbo);
	glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(vertex), NULL, GL_STATIC_DRAW); // orphan the buffer
	glBufferSubData(GL_ARRAY_BUFFER, 0, 6 * sizeof(vertex), vertex);

	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(GLuint), NULL, GL_STATIC_DRAW); // orphan the buffer
	glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, 6 * sizeof(GLuint), indices);

	//glBindBuffer(GL_ARRAY_BUFFER, 0);
}

void Mesh::Draw()
{
	glBindVertexArray(vao);

	//glEnable(GL_CULL_FACE);
	//glCullFace(GL_FRONT);
	//glFrontFace(GL_CW);
	glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, NULL);

	//glBindVertexArray(0);
}

I w mainie

	glm::mat4 model;
		model = glm::rotate(model, glm::radians(-55.0f), glm::vec3(1.0, 0.0, 0.0));

		glm::mat4 view;
		view = glm::translate(view, glm::vec3(0.0f, 0.0f, -3.0f));

		glm::mat4 projection;
		projection = glm::perspective(glm::radians(45.0f), 1280.0f / 720, 0.1f, 100.0f);

		GLint u_model = shader.GetUniformLocation("u_model");
		GLint u_view = shader.GetUniformLocation("u_view");
		GLint u_projection = shader.GetUniformLocation("u_projection");

		glUniformMatrix4fv(u_model, 1, GL_FALSE, glm::value_ptr(model));
		glUniformMatrix4fv(u_view, 1, GL_FALSE, glm::value_ptr(view));
		glUniformMatrix4fv(u_projection, 1, GL_FALSE, glm::value_ptr(projection));

		Rect destRect = { -0.5f, -0.5f, 1.0f, 1.0f };
		Rect uvRect = { 0.0f, 0.0f, 1.0f, 1.0f };
		ColorRGBA color = { 255, 255, 128, 0 };

		mesh.CreateQuad(destRect, uvRect, color);
		mesh.Draw();

Potem jeszcze zmieniałem z modelview i nadal taki sam efekt bez tekstury, bez sprite batcha. Chyba jest to dużo prościej zrobione.

0
czaffik napisał(a):

@SiemkaElkoTszyPiencZerko: klasa Tekstura u ciebie powinna się raczej nazywać prostokąt albo sprite, tymczasem zawiera w sobie i teksturę (która nazywa się tekstureCache i sprite'a który tworzy siatkę i przekazuje ją do shadera, a wystarczy sama klasa sprite która zawiera w sobie teksturę którą nałożysz na prostokąt, a klasa Glyph całkiem już zaciemnia obraz, pamiętaj że im więcej masz takich podziałów kiedy ich nie potrzeba tym trudniej dojść o co chodzi.

Jak byś proponował wtedy to zrobić?

0
  1. W Mesh::CreateQuad utworzyłeś bufory vbo i ebo ale nie stowarzyszyłeś z nimi żadnego vao, co prawda w Mesh::CreateVertexArray masz utworzone i zbindowane vao ale pod koniec funkcji masz glBindVertexArray(0); w funkcji Mesh::Draw masz:
glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, NULL);

problem w tym że w tym vao nie masz zapisanych żadnych informacji na temat werteksów które przepchnąłeś do vbo i ebo
czyli przed tym:

glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(vertex), NULL, GL_STATIC_DRAW); // orphan the buffer
glBufferSubData(GL_ARRAY_BUFFER, 0, 6 * sizeof(vertex), vertex); 
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(GLuint), NULL, GL_STATIC_DRAW); // orphan the buffer
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, 6 * sizeof(GLuint), indices);

powinno być to:

glBindVertexArray(vao);
  1. Teraz możesz stworzyć klasę tekstury, np coś takiego:
class Texture
{
    public:
        Texture(std::string fileName);
        Texture(SDL_Surface *surface);
        virtual ~Texture();

        void bind() { glBindTexture(GL_TEXTURE_2D, id); }

    protected:
        void createFromFile(std::string fileName);
        void createFromSurface(SDL_Surface *surface);
        SDL_Surface* flipImage(SDL_Surface *surface);

        GLuint id;

    private:
};

i dorzucić ją do klasy Mesh.

0

Chyba niekoniecznie właśnie z tym bindowaniem vao w create quad, bo normalnie kwadrat sie rysuje tylko się nie chce tak przechylić o ten kąt. Chyba, że własnie przez to, że tego nie ma nie chce się przechylić. Nawet właściwie nie powinno być vao zbindowane, bo pokazuje się błąd.

i dorzucić ją do klasy Mesh.

Czyli to klasa texture ma być w mesh a nie mesh w texture :O

0

1."Chyba niekoniecznie właśnie z tym bindowaniem vbo w create quad, bo normalnie kwadrat sie rysuje" - raczej nie powinien się rysować, vbo powinno być podpięte pod jakieś vao. Vao to taki główny identyfikator siatki, vbo przechowuje informacje o werteksach a ebo je indeksuje (coś w uproszczeniu w taki sposób chyba to wygląda), tak czy siak bez vao się nie rysuje sprawdzałem.

2."bo normalnie kwadrat sie rysuje tylko się nie chce tak przechylić o ten kąt" - nie wiem, jakby informacje o macierzach nie chciały ci się do shadera przesłać.

3."Czyli to klasa texture ma być w mesh a nie mesh w texture :O" - dokładnie, bo tekstura to tylko obrazek narzucany na jakiś kształt

0

na pewno masz zbindowany odpowiedni shader przed tym ustawianiem uniformów?

Zrobiłem taki test, że zrobiłem nowy uniform int u_poss (nazwa wiem, że znikąd ale na szybko pisane), ustawiłem w maine go na 2 i pomnożyłem pozycje y bezpośrednio w shaderze przez ten uniform i dało nam wyższy prostokąt, co znaczy, że inne uniformy działają dobrze.

0

Ja rozumiem że to właśnie coś nie działa i nie wchodzi, jak przemnożyłeś pozycję y przez 2 i wychodzi to samo to chyba coś nie działa.
Zrób sobie uniform u_color i we fragment shaderze zrób

outColor = u_color;

jak kolor siatki wyjdzie taki jaki podałeś w zmiennej u_color (np zielony) to znaczy że działa, jak będzie czarny to nie działa.

0

@SiemkaElkoTszyPiencZerko: widzę że masz tak wielką awersję do programów typu hello-world że nie możesz pozbyć się tych klas, a zaciemniają niestety sytuację...

Pozwól że pomogę. Bo dobrze jest najpierw napisać absolutne minimum, które może nawet nie jest pięknym kodem, ale przynajmniej działa.
Użyłem Visual Studio 2010 pod Windows XP (awaryjnie bo dysk z Win 10 padł i nie kupiłem jeszcze nowego).

Z wyjątkiem nagłówka glext.h program nie używa żadnych innych zewnętrznych bibliotek które trzeba byłoby doinstalowywać do VS2010: nie ma GLM (bo nie ma przekształceń macierzowych), nie ma GLUT-a, GLFW ani innych GL-fuj, GL-pluj ani SDL-i. Po prostu WinAPI.

Rysowany jest statyczny obrazek. Nie ma nawet "pętli rysującej". Po prostu rysuje na starcie, a potem gdy Windowsowi się zechce odświeżyć okienko.

Samo okienko wygląda tak:

#include <Windows.h>
#include <GL/GL.h>
#include "glext.h"

PFNGLGENVERTEXARRAYSPROC glGenVertexArrays;
PFNGLBINDVERTEXARRAYPROC glBindVertexArray;
PFNGLGENBUFFERSPROC glGenBuffers;
PFNGLBINDBUFFERPROC glBindBuffer;
PFNGLCREATESHADERPROC glCreateShader;
PFNGLSHADERSOURCEPROC glShaderSource;
PFNGLCOMPILESHADERPROC glCompileShader;
PFNGLCREATEPROGRAMPROC glCreateProgram;
PFNGLATTACHSHADERPROC glAttachShader;
PFNGLLINKPROGRAMPROC glLinkProgram;
PFNGLUSEPROGRAMPROC glUseProgram;
PFNGLBUFFERDATAPROC glBufferData;
PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray;
PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer;

void init_scene()
{
	glClearColor(1, 1, 1, 0);
}

void render_scene()
{
	glClear(GL_COLOR_BUFFER_BIT);
	glFlush();
}

void init_opengl(HWND hwnd)
{
	PIXELFORMATDESCRIPTOR pfd = { sizeof(pfd), 1 };
	pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
	pfd.cColorBits = 32;
	pfd.cDepthBits = 24;
	HDC dc = GetDC(hwnd);
	SetPixelFormat(dc, ChoosePixelFormat(dc, &pfd), NULL);
	HGLRC rc = wglCreateContext(dc);
	wglMakeCurrent(dc, rc);

	glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC)wglGetProcAddress("glGenVertexArrays");
	glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC)wglGetProcAddress("glBindVertexArray");
	glGenBuffers = (PFNGLGENBUFFERSPROC)wglGetProcAddress("glGenBuffers");
	glBindBuffer = (PFNGLBINDBUFFERPROC)wglGetProcAddress("glBindBuffer");
	glCreateShader = (PFNGLCREATESHADERPROC)wglGetProcAddress("glCreateShader");
	glShaderSource = (PFNGLSHADERSOURCEPROC)wglGetProcAddress("glShaderSource");
	glCompileShader = (PFNGLCOMPILESHADERPROC)wglGetProcAddress("glCompileShader");
	glCreateProgram = (PFNGLCREATEPROGRAMPROC)wglGetProcAddress("glCreateProgram");
	glAttachShader = (PFNGLATTACHSHADERPROC)wglGetProcAddress("glAttachShader");
	glLinkProgram = (PFNGLLINKPROGRAMPROC)wglGetProcAddress("glLinkProgram");
	glUseProgram = (PFNGLUSEPROGRAMPROC)wglGetProcAddress("glUseProgram");
	glBufferData = (PFNGLBUFFERDATAPROC)wglGetProcAddress("glBufferData");
	glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC)wglGetProcAddress("glEnableVertexAttribArray");
	glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC)wglGetProcAddress("glVertexAttribPointer");
}

LRESULT __stdcall WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch (uMsg)
	{
	case WM_CREATE:
		init_opengl(hwnd);
		init_scene();
		break;
	case WM_PAINT:
		render_scene();
		ValidateRect(hwnd, NULL);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hwnd, uMsg, wParam, lParam);
	}
	return 0;
}

int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int nCmdShow)
{
	CoInitialize(NULL);
	WNDCLASS wc = {};
	wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;  
	wc.lpfnWndProc = WindowProc;
	wc.hInstance = hInstance;  
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	wc.lpszClassName = L"blablabla";
	ATOM atom = RegisterClass(&wc);
	HWND hwnd = CreateWindow(
		MAKEINTATOM(atom),
		L"Test OpenGL",
	    WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
		CW_USEDEFAULT, CW_USEDEFAULT,  
		500, 500,
		(HWND)NULL, (HMENU)NULL, hInstance, (LPVOID)NULL
	);
	ShowWindow(hwnd, nCmdShow);
	MSG msg;
	while (GetMessage(&msg, NULL, 0, 0))
    {
		TranslateMessage(&msg); 
        DispatchMessage(&msg); 
    }
	return msg.wParam;
}

OK. To nam daje białe okno. Interesują nas dwie funkcje: init_scene() i render_scene(). Reszta to WinAPI-owe „śmieci”. W init_scene mamy ustawienie koloru na biały, a w render_scene czyszczenie okna.

Linie z PFNGL-itd. są potrzebne bo nie mamy żadnej gotowej ładowarki do OpenGL-a, przez co (pod Windows) większość funkcji trzeba załadować przez wglGetProcAddress.
Typy wskaźnikowe (PFNGL...) są zdefiniowane w glext.h.

W podany wyżej sposób powstaje nam kontekst OpenGL “compatibility”, ale tylko dlatego że kod inicjalizujący “core” byłby sporo dłuższy, a chciałem żeby kod był jak najkrótszy. Mimo to w dalszej części postaram się trzymać wymagań “core”.

Kontekst OpenGL “core” wymaga użycia VAO i VBO. Niech im tam będzie:

void init_scene()
{
	...
	
	GLuint vao;
	glGenVertexArrays(1, &vao);
	glBindVertexArray(vao);

	GLuint vbo;
	glGenBuffers(1, &vbo);
	glBindBuffer(GL_ARRAY_BUFFER, vbo);
}

Proszsz. Te sześć linijek załatwia sprawę. Jest VAO, jest VBO i nie będziemy mówić o nich więcej.
Okej. W dalszej kolejności idą shadery. Absolutnie najprostsze, najpierw bez teksturowania:

void init_scene()
{
	...

	GLuint vs = glCreateShader(GL_VERTEX_SHADER);
	const char *vs_source =
		"#version 330\n                            "
		"layout (location = 0) in vec2 a_position; "
		"void main()                               "
	    "{                                         "
	    "    gl_Position = a_position;             "
		"}                                         ";
	glShaderSource(vs, 1, (GLchar**)&vs_source, NULL);
	glCompileShader(vs);
	GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
	const char *fs_source =
		"#version 330\n                          "
		"layout (location = 0) out vec4 o_color; "
		"void main()                             "
		"{                                       "
		"    o_color = vec4(1.0, 0.0, 0.0, 1.0); "
		"}                                       ";
	glShaderSource(fs, 1, (GLchar**)&fs_source, NULL);
	glCompileShader(fs);
	
	GLuint prog = glCreateProgram();
	glAttachShader(prog, vs);
	glAttachShader(prog, fs);
	glLinkProgram(prog);
	glUseProgram(prog);
}

Vertex shader nie robi nic (przepycha pozycję dalej…) a fragment shader rysuje na czerwono.
No to narysujmy coś:


struct vertex_t
{
	float x, y;
};

void init_scene()
{
	....

	const vertex_t vertices[] = { { -0.5, 0.5 }, { -0.5, -0.5 }, { 0.5, -0.5 }, { -0.5, 0.5 }, { 0.5, -0.5 }, { 0.5, 0.5 } };
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
	glEnableVertexAttribArray(0);
	glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(vertex_t), 0);
}

void render_scene()
{
	glClear(GL_COLOR_BUFFER_BIT);
	glDrawArrays(GL_TRIANGLES, 0, 6);
	glFlush();
}

Ponieważ rysujemy statyczny obrazek, do render_scene trafia tylko samo rysowanie glDrawArrays, wszystko inne ustawiane jest tylko raz.

Efekt:
testd.PNG
Tadaam.

Teraz tekstura.

#include "texloader.h"

Kod texloader.h/texloader.cpp w załączniku. Nie będziemy zaśmiecać posta.

Zmienia nam się struktura wierzchołka:

struct vertex_t
{
	struct { float x, y; } position;
	struct { float u, v; } texCoord;
};

W funkcji init_scene zmieniamy kod shaderów:

	const char *vs_source =
		"#version 330\n                                    "
		"layout (location = 0) in vec2 a_position;         "
		"layout (location = 1) in vec2 a_texCoord;         "
		"out vec2 v_texCoord;                              "
		"void main()                                       "
	    "{                                                 "
		"    gl_Position = vec4(a_position, 0.0, 1.0);     "
		"    v_texCoord = a_texCoord;                      "
		"}                                                 ";
	const char *fs_source =
		"#version 330\n                                 "
		"in vec2 v_texCoord;                            "
		"uniform sampler2D u_texture0;                  "
		"layout (location = 0) out vec4 o_color;        "
		"void main()                                    "
		"{                                              "
		"    o_color = texture(u_texture0, v_texCoord); "
		"}                                              ";

i na końcu same dane które idą do bufora:

	const vertex_t vertices[] =
		{ { { -0.5, 0.5 }, { 0, 1 } }, { { -0.5, -0.5 }, { 0, 0 } }, { { 0.5, -0.5 }, { 1, 0 } },
	      { { -0.5, 0.5 }, { 0, 1 } }, { { 0.5, -0.5 }, { 1, 0 } }, { { 0.5, 0.5 }, { 1, 1 } } };
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
	glEnableVertexAttribArray(0);
	glEnableVertexAttribArray(1);
	glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (void*)offsetof(vertex_t, position));
	glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (void*)offsetof(vertex_t, texCoord));

	GLuint texture = LoadTexture(L"tex.png");
	glBindTexture(GL_TEXTURE_2D, texture);

Funkcja LoadTexture (z texloader.h) przyjmuje nazwę pliku (może być jpg, png, i inne obsługiwane przez Windows formaty). Sam plik powinien być w tym samym katalogu co exek.

teste.PNG

0

@Azarien Pozwoliłem sobie użyć sdla, bo z winem jakieś błędy wyskakiwały, a ja w ogóle tego nie znam i też mi sie nie chce szukać w internecie o co w tym chodzi.

Zrobiłem reszte (init i render) tak jak napisałeś i w ogóle nie koloruje mi się prostokąt. Cały czarny.

void init()
{
	GLuint vao;
	glGenVertexArrays(1, &vao);
	glBindVertexArray(vao);

	GLuint vbo;
	glGenBuffers(1, &vbo);
	glBindBuffer(GL_ARRAY_BUFFER, vbo);

	GLuint vs = glCreateShader(GL_VERTEX_SHADER);
	const char *vs_source =
		"#version 330\n                            "
		"layout (location = 0) in vec2 a_position; "
		"void main()                               "
		"{                                         "
		"    gl_Position = a_position;             "
		"}                                         ";
	glShaderSource(vs, 1, (GLchar**)&vs_source, NULL);
	glCompileShader(vs);
	GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
	const char *fs_source =
		"#version 330\n                          "
		"layout (location = 0) out vec4 o_color; "
		"void main()                             "
		"{                                       "
		"    o_color = vec4(1.0, 0.0, 0.0, 1.0); "
		"}                                       ";
	glShaderSource(fs, 1, (GLchar**)&fs_source, NULL);
	glCompileShader(fs);

	GLuint prog = glCreateProgram();
	glAttachShader(prog, vs);
	glAttachShader(prog, fs);
	glLinkProgram(prog);
	glUseProgram(prog);

	const vertex_t vertices[] = { 
		{ -0.5,  0.5 },
		{ -0.5, -0.5 },
		{  0.5, -0.5 },
		{ -0.5,  0.5 },
		{  0.5, -0.5 },
		{  0.5,  0.5 } 
	};
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
	glEnableVertexAttribArray(0);
	glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(vertex_t), 0);
}

void render()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glDrawArrays(GL_TRIANGLES, 0, 6);
	glFlush();
}

a tutaj sam main

struct vertex_t
{
	float x, y;
};

void init();
void render();

int main(int argc, char*args[])
{
	SDL_Init(SDL_INIT_EVERYTHING);

	SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

	SDL_Window* window = SDL_CreateWindow("name", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_WINDOW_OPENGL);
	SDL_GLContext context = SDL_GL_CreateContext(window);

	glewExperimental = true;
	glewInit();

	bool quit = false;
	SDL_Event event;

	init();

	while (!quit) {
		while (SDL_PollEvent(&event)) {
			if (event.type == SDL_QUIT) {
				SDL_Quit();
				exit(0);
			}
		}

		glClearDepth(1.0f);
		glClearColor(0.5f, 0.5f, 0.5f, 0.5f);
		//glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

		render();

		SDL_GL_SwapWindow(window);
	}
	return 0;
}

praktycznie skopiowałem wszystko

screenshot-20180113221450.png

0

W moim kodzie powyżej była jedna rzecz nie działająca w Core Profile, a było ją trudno znaleźć bo była w texloader.cpp.

Zamiast

glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);

trzeba dać

PFNGLGENERATEMIPMAPPROC glGenerateMipmap = (PFNGLGENERATEMIPMAPPROC)wglGetProcAddress("glGenerateMipmap");
glGenerateMipmap(GL_TEXTURE_2D);

ale za wywołaniem glTexImage2D.
Alternatywnie, można wyłączyć mipmapping (GL_LINEAR zamiast GL_LINEAR_MIPMAP_LINEAR) albo zbudować mipmapę ręcznie.

Samo core profile to inna funkcja WinMain:

PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB;
...
int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int nCmdShow)
{
	CoInitialize(NULL);
	WNDCLASS wc = {};
	wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;  
	wc.lpfnWndProc = DefWindowProc;
	wc.hInstance = hInstance;  
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	wc.lpszClassName = L"blablabla";
	ATOM atom = RegisterClass(&wc);
	HWND hwnd = CreateWindow(MAKEINTATOM(atom), L"", WS_POPUP, 0, 0, 100, 100, NULL, NULL, hInstance, NULL);
	PIXELFORMATDESCRIPTOR pfd = { sizeof(pfd), 1 };
	pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
	pfd.cColorBits = 32;
	HDC dc = GetDC(hwnd);
	SetPixelFormat(dc, ChoosePixelFormat(dc, &pfd), NULL);
	HGLRC rc = wglCreateContext(dc);
	wglMakeCurrent(dc, rc);
	wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB");
	wglMakeCurrent(dc, NULL);
	wglDeleteContext(rc);
	DestroyWindow(hwnd);
	UnregisterClass(MAKEINTATOM(atom), hInstance);
	wc.lpfnWndProc = WindowProc;
	atom = RegisterClass(&wc);
	hwnd = CreateWindow(
		MAKEINTATOM(atom),
		L"Test OpenGL",
	    WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
		CW_USEDEFAULT, CW_USEDEFAULT,  
		500, 500,
		(HWND)NULL, (HMENU)NULL, hInstance, (LPVOID)NULL
	);
	ShowWindow(hwnd, nCmdShow);
	MSG msg;
	while (GetMessage(&msg, NULL, 0, 0) != 0)
    {
		TranslateMessage(&msg); 
        DispatchMessage(&msg); 
    }
	return msg.wParam;
}

a wywołanie wglCreateContext zastąpione czymś takim;

	int attribs[] =
	{
		WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
		WGL_CONTEXT_MINOR_VERSION_ARB, 3,
		WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
		0
	};
	HGLRC rc = wglCreateContextAttribsARB(dc, NULL, attribs);
0

Zawsze możesz jeszcze posprawdzać czy ci błędu nie wywala:
takie coś po kompilacji shadera:

s = glCreateShader(GL_FRAGMENT_SHADER);
source = loadShaderFile("vert.glsl").c_str();
glShaderSource(s, 1, &source, nullptr);
glCompileShader(s);
glAttachShader(shaderID, s);

GLint vShaderCompiled = GL_TRUE;
glGetShaderiv(s, GL_COMPILE_STATUS, &vShaderCompiled);

if (vShaderCompiled != GL_TRUE)
{
    GLint length, len;
    glGetShaderiv(s, GL_INFO_LOG_LENGTH, &length);
    GLchar *info = new GLchar[length];
    glGetShaderInfoLog(s, length, &len, info);

    std::stringstream err;
    err << "\nShaderProgram::createShader: Nie mozna skompilowac shadera: " << ". \nBlad: " << info;
    std::cout << err.str() << std::endl;
}

takie coś po zlinkowaniu shadera:

glLinkProgram(shaderID);

GLint programSuccess = GL_TRUE;
glGetProgramiv(shaderID, GL_LINK_STATUS, &programSuccess);
if(programSuccess != GL_TRUE)
{
    std::string error;
    switch (glGetError())
    {
        case 1280:
            error = "GL_INVALID_ENUM";
            break;
        case 1281:
            error = "GL_INVALID_VALUE";
            break;
        case 1282:
            error = "GL_INVALID_OPERATION";
            break;
        case 1283:
            error = "GL_STACK_OVERFLOW";
            break;
        case 1284:
            error = "GL_STACK_UNDERFLOW";
            break;
        case 1285:
            error = "GL_OUT_OF_MEMORY";
            break;
        default:
            error = "UNKNOWN";
    }

    std::stringstream err;
    err << "ShaderProgram::ShaderProgram: Nie mozna utworzyc programu shadera: " << "\nblad: " << error;
    std::cout << err.str() << std::endl;
}

Napisałem prosty programik na jeden plik main : https://pastebin.com/uktdta89 aby wyświetlić prostokąt z teksturką i coś nie działa, sprawdzam i takie coś wyskakuje:
titleClipboard01.jpg
może coś pomyliłem, może o czymś zapomniałem, sam nie mogę się doszukać, tak więc żeby stworzyć działający program trzeba niestety trochę pokombinować.

Edit: z tego co czytałem to glew może być problematyczny, nie wiem ile to prawdy ale spróbuj może inną bibliotekę do rozszerzeń, np glad.

0

Problem rozwiązany. Trzeba było zrobić glm::mat4 model = glm::mat4(1.0f); :D Trochę agenci z nas.

@czaffik

Ustaw model i view na macierz jednostkową przed dokonaniem operacji:

glm::mat4 model = glm::mat4();
model = glm::translate(model, glm::vec3(0.0f, 0.0f, -3.0f));

Może jak o tym pisałeś to zapomniałeś jedynki dopisać, albo po prostu powinno działać bez tego, ale skoro działa to tylko się cieszyć! :D

Dzięki chłopaki za poświęcony czas, bardzo dziękuje.

1 użytkowników online, w tym zalogowanych: 0, gości: 1