skybox but its mirrored
@ -1,29 +0,0 @@
|
||||
0. Do tej pory nasze obiekty znajdowały się głównie w płaszczyźnie X-Z, w której poruszał i obracał się statek (i kamera). Teraz nie będziemy się już ograniczać do ruchu na płaszczyźnie. Planety będą znajdować się w dowolnych miejscach trójwymiarowej przestrzeni. Aby wygodnie poruszać się w trzech wymiarach, stworzymy ruch kamery oparty na kwaternionach.
|
||||
|
||||
1. Wyświetl większą liczbę planet (np. 10) w przestrzeni trójwymiarowej (tak, aby nie znajdowały się tylko w płaszczyźnie). Możesz wylosować w funkcji init() pozycje planet (używając np. funkcji vec3 glm::ballRand(float R), która zwraca losowy wektor w kuli o promieniu R), zapisać je w tablicy lub w std::vector i w funkcji renderScene() umieścić pętlę iterującą po tablicy, w której wywoływane będzie rysowanie planety o zadanej pozycji.
|
||||
|
||||
2. Chcemy stworzyć kamerę, w której ruch myszą góra-dół spowoduje obrót kamery wokół lokalnej osi X, a ruch lewo-prawo - obrót kamery wokół lokalnej osi Y. Należy zacząć od usunięcia zawartości funkcji createCameraMatrix(), którą w tym zadaniu napiszemy od nowa.
|
||||
|
||||
a) W głównym pliku C++ pojawiła się nowa funkcja void mouse(int x, int y), która jest wywoływana przy każdej zmianie pozycji kursora w oknie. Stwórz zmienną (lub zmienne) globalne, w której po zakończeniu funkcji mouse() będzie znajdować się różnica między poprzednią a aktualną pozycją kursora (osobno względem osi X i Y ekranu). Różnica ta zostanie wykorzystana do kontrolowania obrotu kamery.
|
||||
|
||||
b) W funkcji createCameraMatrix() oblicz kwaternion reprezentujący rotację spowodowaną przez ruch kursora między poprzednią a aktualną klatką animacji (zmienne z punktu 2a). Możesz użyć funkcji glm::quat glm::angleAxis(float angle, glm::vec3 axis), która zwraca kwaternion reprezentujący obrót wokół podanej osi o podany kąt. Oblicz obrót dla osi X (wynikający z ruchu myszki w kierunku Y) i dla osi Y (wynikający z ruchu myszki w kierunku X) i połącz je, mnożąc ze sobą kwaterniony (kolejność mnożenia macierzy jak zwykle nie jest dowolna. Jednak w tym przypadku - ponieważ są to tylko inkrementalne, a nie całościowe obroty - nie ma do dużego znaczenia). Po obliczeniu macierzy zmiany rotacji, należy wyzerować zmienne z podpunktu a)!
|
||||
|
||||
c) Oblicz nowy obrót (zmienna globalna rotation), poprzez:
|
||||
rotation = rotationChange * rotation; // rotationChange to kwaternion z podpunktu b)
|
||||
Z powodu potencjalnych niedokładności numerycznych, otrzymany kwaternion należy znormalizować (funkcja glm::quat glm::normalize(glm::quat q)).
|
||||
|
||||
d) W plikach Camera.h i Camera.cpp znajduje się nowa funkcja Core::createViewMatrixQuat(), która generuje macierz kamery z pozycji i kwaterniona zawierającego obrót, której należy teraz użyć w miejsce używanego wcześniej Core::createViewMatrix().
|
||||
|
||||
e) Należy także w każdym wywołaniu funkcji createCameraMatrix() aktualizować wartości funkcji cameraDir i cameraSide (aby poprawnie działało przesuwanie kamery w funkcji keyboard()). cameraDir i cameraSide to z definicji wektory, które w przestrzeni kamery mają postać (0,0,-1) i (1,0,0). Aby uzyskać te wektory w przestrzeni świata (bo tam wykonujemy obliczenia przesuwające cameraPos), należy je przekształcić przez ODWROTNY obrót kamery. Można to zrobić mnożąc je przez (odwrócony) kwaternion rotation.
|
||||
Pseudokod:
|
||||
cameraDir = odwrotnoscRotation * (0, 0, -1)
|
||||
Odwrotność kwaterniona można uzyskać funkcją glm::quat glm::inverse(glm::quat q).
|
||||
|
||||
3. Popraw kod przyczepiający statek do kamery.
|
||||
a) Macierz obrotu będąca składową shipModelMatrix obliczona przez "glm::rotate(-cameraAngle, glm::vec3(0,1,0))" musi zostać zastąpiona inną macierzą, wynikającą z nowego, bardziej skomplikowanego obrotu kamery zapisanego w kwaternionie. Macierz obrotu 4x4 można uzyskać z kwaterniona używając funkcji glm::mat4 glm::mat4_cast(glm::quat q). Znów jednak należy użyć ODWROTNEGO kwaterniona obrotu kamery (* - wyjaśnienie na dole).
|
||||
|
||||
4. Dodaj obrót kamery wokół trzeciej osi (lokalnej osi Z) przy użyciu przycisków Z i X na klawiaturze.
|
||||
|
||||
|
||||
|
||||
(*)Macierz obrotu kamery działa z przestrzeni świata do przestrzeni kamery. Ponieważ chcemy, aby statek był "tożsamy z kamerą", to jego macierz świata powinna być właściwie przekształceniem z przestrzeni kamery do przestrzeni świata - czyli ODWROTNOŚCIĄ przekształcenia kamery. Można to samo rozumowanie zastosować do pełnej macierzy kamery (razem z translacją), ale my akurat robimy translację statku w osobnym kroku).
|
@ -14,8 +14,10 @@
|
||||
<ClCompile Include="src\Bubble.cpp" />
|
||||
<ClCompile Include="src\Camera.cpp" />
|
||||
<ClCompile Include="src\main_6_1.cpp" />
|
||||
<ClCompile Include="src\Model.cpp" />
|
||||
<ClCompile Include="src\Render_Utils.cpp" />
|
||||
<ClCompile Include="src\Shader_Loader.cpp" />
|
||||
<ClCompile Include="src\Skybox.cpp" />
|
||||
<ClCompile Include="src\SOIL\image_DXT.c" />
|
||||
<ClCompile Include="src\SOIL\image_helper.c" />
|
||||
<ClCompile Include="src\SOIL\SOIL.c" />
|
||||
@ -25,9 +27,13 @@
|
||||
<ItemGroup>
|
||||
<ClInclude Include="src\Bubble.h" />
|
||||
<ClInclude Include="src\Camera.h" />
|
||||
<ClInclude Include="src\Mesh.h" />
|
||||
<ClInclude Include="src\Model.h" />
|
||||
<ClInclude Include="src\objload.h" />
|
||||
<ClInclude Include="src\Render_Utils.h" />
|
||||
<ClInclude Include="src\Shader.h" />
|
||||
<ClInclude Include="src\Shader_Loader.h" />
|
||||
<ClInclude Include="src\Skybox.h" />
|
||||
<ClInclude Include="src\SOIL\image_DXT.h" />
|
||||
<ClInclude Include="src\SOIL\image_helper.h" />
|
||||
<ClInclude Include="src\SOIL\SOIL.h" />
|
||||
@ -39,6 +45,10 @@
|
||||
<ItemGroup>
|
||||
<None Include="shaders\shader_color.frag" />
|
||||
<None Include="shaders\shader_color.vert" />
|
||||
<None Include="shaders\shader_cube.frag" />
|
||||
<None Include="shaders\shader_cube.vert" />
|
||||
<None Include="shaders\shader_test.frag" />
|
||||
<None Include="shaders\shader_test.vert" />
|
||||
<None Include="shaders\shader_tex.frag" />
|
||||
<None Include="shaders\shader_tex.vert" />
|
||||
</ItemGroup>
|
||||
|
@ -51,6 +51,12 @@
|
||||
<ClCompile Include="src\Bubble.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\Skybox.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\Model.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="src\objload.h">
|
||||
@ -59,9 +65,6 @@
|
||||
<ClInclude Include="src\Render_Utils.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\Shader_Loader.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\Camera.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
@ -89,6 +92,21 @@
|
||||
<ClInclude Include="src\Bubble.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\Shader_Loader.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\Skybox.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\Model.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\Mesh.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\Shader.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="shaders\shader_color.frag">
|
||||
@ -103,5 +121,17 @@
|
||||
<None Include="shaders\shader_tex.vert">
|
||||
<Filter>Shader Files</Filter>
|
||||
</None>
|
||||
<None Include="shaders\shader_cube.frag">
|
||||
<Filter>Shader Files</Filter>
|
||||
</None>
|
||||
<None Include="shaders\shader_cube.vert">
|
||||
<Filter>Shader Files</Filter>
|
||||
</None>
|
||||
<None Include="shaders\shader_test.frag">
|
||||
<Filter>Shader Files</Filter>
|
||||
</None>
|
||||
<None Include="shaders\shader_test.vert">
|
||||
<Filter>Shader Files</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
10
cw 6/shaders/shader_cube.frag
Normal file
@ -0,0 +1,10 @@
|
||||
#version 430 core
|
||||
|
||||
out vec4 FragColor;
|
||||
in vec3 TexCoords;
|
||||
|
||||
uniform samplerCube skybox;
|
||||
void main()
|
||||
{
|
||||
FragColor = texture(skybox,TexCoords);
|
||||
}
|
14
cw 6/shaders/shader_cube.vert
Normal file
@ -0,0 +1,14 @@
|
||||
#version 430 core
|
||||
|
||||
layout(location = 0) in vec3 vertexPosition;
|
||||
|
||||
out vec3 TexCoords;
|
||||
uniform mat4 projection;
|
||||
uniform mat4 view;
|
||||
|
||||
void main()
|
||||
{
|
||||
TexCoords = vertexPosition;
|
||||
gl_Position = projection * view * vec4(vertexPosition, 1.0);
|
||||
|
||||
}
|
152
cw 6/shaders/shader_test.frag
Normal file
@ -0,0 +1,152 @@
|
||||
#version 430 core
|
||||
struct Light {
|
||||
float ambient;
|
||||
float diffuse;
|
||||
float specular;
|
||||
|
||||
float constant;
|
||||
float linear;
|
||||
float quadratic;
|
||||
};
|
||||
|
||||
struct PointLight{
|
||||
vec3 position;
|
||||
|
||||
float ambient;
|
||||
float diffuse;
|
||||
float specular;
|
||||
|
||||
float constant;
|
||||
float linear;
|
||||
float quadratic;
|
||||
|
||||
};
|
||||
uniform sampler2D texture_diffuse;
|
||||
uniform sampler2D texture_specular;
|
||||
uniform sampler2D texture_normal;
|
||||
|
||||
uniform vec3 lightDir;
|
||||
uniform vec3 cameraPos;
|
||||
uniform float Distroyed;
|
||||
|
||||
in vec2 interpTexCoord;
|
||||
in vec3 lightDirTS;
|
||||
//in vec3 lightDirTS2;
|
||||
in vec3 viewDirTS;
|
||||
in vec3 vertPosition;
|
||||
in vec3 lightPosition;
|
||||
in vec3 viewDirection;
|
||||
|
||||
vec4 CalcDirLight(vec3 LightDir,Light light,vec3 viewDir, float distance)
|
||||
{
|
||||
float attenuation = 1.0/(light.constant + light.linear * distance + light.quadratic * (distance*distance));
|
||||
vec3 L = normalize(-lightDirTS);
|
||||
vec3 V = normalize(viewDirTS);
|
||||
vec3 N = normalize(vec3(0,0,1));
|
||||
vec3 R = reflect(-normalize(L), N);
|
||||
|
||||
N = texture2D(texture_normal, interpTexCoord).rgb;
|
||||
N = N * 2 - 1;
|
||||
N = normalize(N);
|
||||
|
||||
light.diffuse = max(0, dot(N, L));
|
||||
vec3 diffuse = light.diffuse *texture2D(texture_diffuse, interpTexCoord).rgb;
|
||||
float specular_pow = 5;
|
||||
light.specular = pow(max(0, dot(R, V)), specular_pow);
|
||||
vec3 specular = light.specular *texture2D(texture_specular, interpTexCoord).rgb;
|
||||
|
||||
vec3 color = texture2D(texture_diffuse, interpTexCoord).rgb;
|
||||
|
||||
diffuse *=attenuation;
|
||||
specular *=attenuation;
|
||||
|
||||
vec3 lightColor = vec3(1);
|
||||
vec3 shadedColor = color * diffuse + lightColor * specular;
|
||||
float ambient = light.ambient;
|
||||
ambient *=attenuation;
|
||||
|
||||
vec4 mixColor = vec4(mix(color, shadedColor, 1.0 - ambient), 1.0) * 0.6f;
|
||||
|
||||
return mixColor;
|
||||
}
|
||||
vec4 CalcPointLight(PointLight light, vec3 fragPos, vec3 viewDir)
|
||||
{
|
||||
vec3 N = normalize(vec3(0,0,1));
|
||||
N = texture2D(texture_normal, interpTexCoord).rgb;
|
||||
N = N * 2 - 1;
|
||||
N = normalize(N);
|
||||
vec3 lightDir = normalize(light.position - fragPos);
|
||||
light.diffuse = max(dot(N, lightDir), 0.0);
|
||||
vec3 reflectDir = reflect(-lightDir, N);
|
||||
|
||||
float specular_pow = 5;
|
||||
light.specular = pow(max(dot(viewDir, reflectDir), 0.0), specular_pow);
|
||||
//float distance = length(light.position - fragPos);
|
||||
float distance = 0.05;
|
||||
float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
|
||||
|
||||
vec3 diffuse = light.diffuse *texture2D(texture_diffuse, interpTexCoord).rgb;
|
||||
vec3 specular = light.specular *texture2D(texture_specular, interpTexCoord).rgb;
|
||||
vec3 color = texture2D(texture_diffuse, interpTexCoord).rgb;
|
||||
|
||||
diffuse *=attenuation;
|
||||
specular *=attenuation;
|
||||
float ambient = light.ambient;
|
||||
ambient *=attenuation;
|
||||
|
||||
vec3 lightColor = vec3(1);
|
||||
|
||||
vec3 shadedColor = color * diffuse + lightColor * specular;
|
||||
vec4 mixColor = vec4(mix(color, shadedColor, 1.0 - ambient), 1.0) * 0.6f;
|
||||
return mixColor;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
|
||||
Light light;
|
||||
light.constant = 1;
|
||||
light.linear = 0.7;
|
||||
light.ambient = 0.7;
|
||||
light.quadratic = 1.8;
|
||||
float distance = 0.05;
|
||||
|
||||
PointLight pointlight;
|
||||
pointlight.constant = 1;
|
||||
pointlight.linear = 0.7;
|
||||
pointlight.ambient = 0.7;
|
||||
pointlight.quadratic = 1.8;
|
||||
pointlight.position = lightPosition;
|
||||
|
||||
vec3 viewDir = viewDirection;
|
||||
vec3 fragPos = vertPosition;
|
||||
|
||||
|
||||
//float attenuation = 1.0/(light.constant + light.linear * distance + light.quadratic * (distance*distance));
|
||||
|
||||
|
||||
//float distance2 = length(lightPosition - vertPosition);
|
||||
//float secondDistance = normalize(-distance2);
|
||||
vec4 Color = CalcDirLight(lightDirTS, light, viewDirTS ,distance);
|
||||
//Color += 2*CalcDirLight(lightDirTS2, light, viewDirTS , distance2);
|
||||
Color += CalcPointLight(pointlight,fragPos,viewDir);
|
||||
|
||||
|
||||
float distroy = Distroyed;
|
||||
float distroyed2 = 1.0;
|
||||
if(distroy == 1.0)
|
||||
{
|
||||
Color = vec4(vec3(0.0,0.5,0.2), 1.0);
|
||||
vec4 toAvoid = vec4(vec3(0.0,0.5,0.2), 1.0);
|
||||
if(Color.rgb == toAvoid.rgb)
|
||||
discard;
|
||||
}
|
||||
//vec4 color = vec4(vec3(0.0,0.5,0.2), 1.0);
|
||||
//vec4 toAvoid = vec4(vec3(0.0,0.5,0.2), 1.0);
|
||||
//if(color.rgb == toAvoid.rgb)
|
||||
// discard;
|
||||
|
||||
|
||||
gl_FragColor = Color;
|
||||
//gl_FragColor = color;
|
||||
}
|
50
cw 6/shaders/shader_test.vert
Normal file
@ -0,0 +1,50 @@
|
||||
#version 430 core
|
||||
|
||||
layout(location = 0) in vec3 vertexPosition;
|
||||
layout(location = 1) in vec2 vertexTexCoord;
|
||||
layout(location = 2) in vec3 vertexNormal;
|
||||
layout(location = 3) in vec3 vertexTangent;
|
||||
layout(location = 4) in vec3 vertexBitangent;
|
||||
|
||||
uniform mat4 modelViewProjectionMatrix;
|
||||
uniform mat4 modelMatrix;
|
||||
|
||||
uniform vec3 lightDir;
|
||||
uniform vec3 cameraPos;
|
||||
|
||||
out vec2 interpTexCoord;
|
||||
out vec3 lightDirTS;
|
||||
//out vec3 lightDirTS2;
|
||||
out vec3 viewDirTS;
|
||||
out vec3 vertPosition;
|
||||
out vec3 lightPosition;
|
||||
out vec3 viewDirection;
|
||||
//out float distToCamera;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 lightPos = vec3(-5.0,7.0,0.0);
|
||||
vec3 vertPos;
|
||||
|
||||
gl_Position = modelViewProjectionMatrix * vec4(vertexPosition, 1.0);
|
||||
//distToCamera = gl_Position.w;
|
||||
vertPos = (modelMatrix * vec4(vertexPosition, 1.0)).xyz;
|
||||
|
||||
vec3 normal = vec3(modelMatrix * vec4(vertexNormal, 0.0));
|
||||
vec3 tangent = vec3(modelMatrix * vec4(vertexTangent, 0.0));
|
||||
vec3 bitangent = vec3(modelMatrix * vec4(vertexBitangent, 0.0));
|
||||
|
||||
mat3x3 TBN = transpose(mat3(tangent, bitangent, normal));
|
||||
|
||||
vec3 lightDir2 = normalize(vertPos - lightPos);
|
||||
vec3 viewDir = normalize(cameraPos - vertPos);
|
||||
lightDirTS = TBN * lightDir;
|
||||
//lightDirTS2 = TBN * lightDir;
|
||||
viewDirTS = TBN * viewDir;
|
||||
|
||||
vertPosition = vertPos;
|
||||
lightPosition = lightPos;
|
||||
viewDirection = viewDir;
|
||||
|
||||
interpTexCoord = vertexTexCoord;
|
||||
}
|
158
cw 6/src/Mesh.h
Normal file
@ -0,0 +1,158 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include "Shader.h"
|
||||
|
||||
#include "glew.h"
|
||||
#include "glm.hpp"
|
||||
#include "assimp/types.h"
|
||||
//#include <glm/gtc/matrix_transform.hpp>
|
||||
|
||||
using namespace std;
|
||||
|
||||
struct Vertex
|
||||
{
|
||||
// Position
|
||||
glm::vec3 Position;
|
||||
// Normal
|
||||
glm::vec3 Normal;
|
||||
// TexCoords
|
||||
glm::vec2 TexCoords;
|
||||
|
||||
glm::vec3 Tangent;
|
||||
|
||||
glm::vec3 Bitangent;
|
||||
};
|
||||
|
||||
struct Texture
|
||||
{
|
||||
GLuint id;
|
||||
string type;
|
||||
aiString path;
|
||||
};
|
||||
|
||||
class Mesh
|
||||
{
|
||||
public:
|
||||
/* Mesh Data */
|
||||
vector<Vertex> vertices;
|
||||
vector<GLuint> indices;
|
||||
vector<Texture> textures;
|
||||
|
||||
/* Functions */
|
||||
// Constructor
|
||||
Mesh( vector<Vertex> vertices, vector<GLuint> indices, vector<Texture> textures )
|
||||
{
|
||||
this->vertices = vertices;
|
||||
this->indices = indices;
|
||||
this->textures = textures;
|
||||
|
||||
|
||||
// Now that we have all the required data, set the vertex buffers and its attribute pointers.
|
||||
this->setupMesh( );
|
||||
}
|
||||
|
||||
// Render the mesh
|
||||
void Draw( GLuint shader )
|
||||
{
|
||||
// Bind appropriate textures
|
||||
GLuint diffuseNr = 1;
|
||||
GLuint specularNr = 1;
|
||||
GLuint normalNr = 1;
|
||||
|
||||
for( GLuint i = 0; i < this->textures.size( ); i++ )
|
||||
{
|
||||
glActiveTexture( GL_TEXTURE0 + i ); // Active proper texture unit before binding
|
||||
// Retrieve texture number (the N in diffuse_textureN)
|
||||
//stringstream ss;
|
||||
//string number;
|
||||
string name = this->textures[i].type;
|
||||
//
|
||||
//if( name == "texture_diffuse" )
|
||||
//{
|
||||
// ss << diffuseNr++; // Transfer GLuint to stream
|
||||
//}
|
||||
//else if( name == "texture_specular" )
|
||||
//{
|
||||
// ss << specularNr++; // Transfer GLuint to stream
|
||||
//}
|
||||
//else if (name == "texture_normal")
|
||||
//{
|
||||
// ss << normalNr++;
|
||||
//}
|
||||
//number = ss.str( );
|
||||
// Now set the sampler to the correct texture unit
|
||||
|
||||
glUniform1i( glGetUniformLocation( shader, ( name //+ number
|
||||
).c_str( ) ), i );
|
||||
// And finally bind the texture
|
||||
glBindTexture( GL_TEXTURE_2D, this->textures[i].id );
|
||||
}
|
||||
|
||||
// Also set each mesh's shininess property to a default value (if you want you could extend this to another mesh property and possibly change this value)
|
||||
//glUniform1f( glGetUniformLocation( shader, "material.shininess" ), 16.0f );
|
||||
|
||||
// Draw mesh
|
||||
glBindVertexArray( this->VAO );
|
||||
glDrawElements( GL_TRIANGLES, this->indices.size( ), GL_UNSIGNED_INT, 0 );
|
||||
glBindVertexArray( 0 );
|
||||
|
||||
// Always good practice to set everything back to defaults once configured.
|
||||
for ( GLuint i = 0; i < this->textures.size( ); i++ )
|
||||
{
|
||||
glActiveTexture( GL_TEXTURE0 + i );
|
||||
glBindTexture( GL_TEXTURE_2D, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
/* Render data */
|
||||
GLuint VAO, VBO, EBO;
|
||||
|
||||
/* Functions */
|
||||
// Initializes all the buffer objects/arrays
|
||||
void setupMesh( )
|
||||
{
|
||||
// Create buffers/arrays
|
||||
glGenVertexArrays( 1, &this->VAO );
|
||||
glGenBuffers( 1, &this->VBO );
|
||||
glGenBuffers( 1, &this->EBO );
|
||||
|
||||
glBindVertexArray( this->VAO );
|
||||
// Load data into vertex buffers
|
||||
glBindBuffer( GL_ARRAY_BUFFER, this->VBO );
|
||||
// A great thing about structs is that their memory layout is sequential for all its items.
|
||||
// The effect is that we can simply pass a pointer to the struct and it translates perfectly to a glm::vec3/2 array which
|
||||
// again translates to 3/2 floats which translates to a byte array.
|
||||
glBufferData( GL_ARRAY_BUFFER, this->vertices.size( ) * sizeof( Vertex ), &this->vertices[0], GL_STATIC_DRAW );
|
||||
|
||||
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, this->EBO );
|
||||
glBufferData( GL_ELEMENT_ARRAY_BUFFER, this->indices.size( ) * sizeof( GLuint ), &this->indices[0], GL_STATIC_DRAW );
|
||||
|
||||
// Set the vertex attribute pointers
|
||||
// Vertex Positions
|
||||
glEnableVertexAttribArray( 0 );
|
||||
glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, sizeof( Vertex ), ( GLvoid * )0 );
|
||||
// Vertex Normals
|
||||
glEnableVertexAttribArray( 1 );
|
||||
glVertexAttribPointer( 1, 3, GL_FLOAT, GL_FALSE, sizeof( Vertex ), ( GLvoid * )offsetof( Vertex, Normal ) );
|
||||
// Vertex Texture Coords
|
||||
glEnableVertexAttribArray(2);
|
||||
glVertexAttribPointer( 2, 2, GL_FLOAT, GL_FALSE, sizeof( Vertex ), ( GLvoid * )offsetof( Vertex, TexCoords ) );
|
||||
|
||||
//w wypadku gdy nie ma tangentow i bitangentow maja one wartosc 0.f w vertexie
|
||||
glEnableVertexAttribArray(3);
|
||||
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, Tangent));
|
||||
|
||||
glEnableVertexAttribArray(4);
|
||||
glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, Bitangent));
|
||||
|
||||
glBindVertexArray( 0 );
|
||||
}
|
||||
};
|
||||
|
||||
|
249
cw 6/src/Model.cpp
Normal file
@ -0,0 +1,249 @@
|
||||
#pragma once
|
||||
|
||||
#include "Model.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
Model::Model(GLchar* path)
|
||||
{
|
||||
this->loadModel(path);
|
||||
}
|
||||
|
||||
// Draws the model, and thus all its meshes
|
||||
void Model::Draw(GLuint shader)
|
||||
{
|
||||
for (GLuint i = 0; i < this->meshes.size(); i++)
|
||||
{
|
||||
this->meshes[i].Draw(shader);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
vector<glm::vec3> Model::getVertexPosition()
|
||||
{
|
||||
vector<glm::vec3> vectorOfVertPos;
|
||||
for (int i = 0; i < meshes[0].vertices.size(); i++)
|
||||
vectorOfVertPos.push_back(meshes[0].vertices[i].Position);
|
||||
return vectorOfVertPos;
|
||||
}
|
||||
|
||||
/* Model Data */
|
||||
// Stores all the textures loaded so far, optimization to make sure textures aren't loaded more than once.
|
||||
|
||||
/* Functions */
|
||||
// Loads a model with supported ASSIMP extensions from file and stores the resulting meshes in the meshes vector.
|
||||
void Model::loadModel(string path)
|
||||
{
|
||||
// Read file via ASSIMP
|
||||
Assimp::Importer importer;
|
||||
const aiScene* scene = importer.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_CalcTangentSpace);
|
||||
|
||||
// Check for errors
|
||||
if (!scene || scene->mFlags == AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) // if is Not Zero
|
||||
{
|
||||
cout << "ERROR::ASSIMP:: " << importer.GetErrorString() << endl;
|
||||
return;
|
||||
}
|
||||
// Retrieve the directory path of the filepath
|
||||
this->directory = path.substr(0, path.find_last_of('/'));
|
||||
|
||||
// Process ASSIMP's root node recursively
|
||||
this->processNode(scene->mRootNode, scene);
|
||||
}
|
||||
|
||||
// Processes a node in a recursive fashion. Processes each individual mesh located at the node and repeats this process on its children nodes (if any).
|
||||
void Model::processNode(aiNode* node, const aiScene* scene)
|
||||
{
|
||||
std::cout << scene->mMaterials << endl;
|
||||
// Process each mesh located at the current node
|
||||
for (GLuint i = 0; i < node->mNumMeshes; i++)
|
||||
{
|
||||
// The node object only contains indices to index the actual objects in the scene.
|
||||
// The scene contains all the data, node is just to keep stuff organized (like relations between nodes).
|
||||
aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
|
||||
this->meshes.push_back(this->processMesh(mesh, scene));
|
||||
}
|
||||
|
||||
// After we've processed all of the meshes (if any) we then recursively process each of the children nodes
|
||||
for (GLuint i = 0; i < node->mNumChildren; i++)
|
||||
{
|
||||
this->processNode(node->mChildren[i], scene);
|
||||
}
|
||||
}
|
||||
|
||||
Mesh Model::processMesh(aiMesh* mesh, const aiScene* scene)
|
||||
{
|
||||
// Data to fill
|
||||
vector<Vertex> vertices;
|
||||
vector<GLuint> indices;
|
||||
vector<Texture> textures;
|
||||
|
||||
// Walk through each of the mesh's vertices
|
||||
for (GLuint i = 0; i < mesh->mNumVertices; i++)
|
||||
{
|
||||
Vertex vertex;
|
||||
glm::vec3 vector; // We declare a placeholder vector since assimp uses its own vector class that doesn't directly convert to glm's vec3 class so we transfer the data to this placeholder glm::vec3 first.
|
||||
|
||||
// Positions
|
||||
// Positions
|
||||
vector.x = mesh->mVertices[i].x;
|
||||
vector.y = mesh->mVertices[i].y;
|
||||
vector.z = mesh->mVertices[i].z;
|
||||
vertex.Position = vector;
|
||||
|
||||
// Normals
|
||||
vector.x = mesh->mNormals[i].x;
|
||||
vector.y = mesh->mNormals[i].y;
|
||||
vector.z = mesh->mNormals[i].z;
|
||||
vertex.Normal = vector;
|
||||
|
||||
//Tangent
|
||||
if (mesh->HasTangentsAndBitangents())
|
||||
{
|
||||
vector.x = mesh->mTangents[i].x;
|
||||
vector.y = mesh->mTangents[i].y;
|
||||
vector.z = mesh->mTangents[i].z;
|
||||
vertex.Tangent = vector;
|
||||
|
||||
vector.x = mesh->mBitangents[i].x;
|
||||
vector.y = mesh->mBitangents[i].y;
|
||||
vector.z = mesh->mBitangents[i].z;
|
||||
vertex.Bitangent = vector;
|
||||
}
|
||||
else
|
||||
{
|
||||
vertex.Tangent = glm::vec3(0.f);
|
||||
vertex.Bitangent = glm::vec3(0.f);
|
||||
}
|
||||
|
||||
|
||||
// Texture Coordinates
|
||||
if (mesh->mTextureCoords[0]) // Does the mesh contain texture coordinates?
|
||||
{
|
||||
glm::vec2 vec;
|
||||
// A vertex can contain up to 8 different texture coordinates. We thus make the assumption that we won't
|
||||
// use models where a vertex can have multiple texture coordinates so we always take the first set (0).
|
||||
vec.x = mesh->mTextureCoords[0][i].x;
|
||||
vec.y = mesh->mTextureCoords[0][i].y;
|
||||
vertex.TexCoords = vec;
|
||||
}
|
||||
else
|
||||
{
|
||||
vertex.TexCoords = glm::vec2(0.0f, 0.0f);
|
||||
}
|
||||
|
||||
vertices.push_back(vertex);
|
||||
}
|
||||
|
||||
// Now wak through each of the mesh's faces (a face is a mesh its triangle) and retrieve the corresponding vertex indices.
|
||||
for (GLuint i = 0; i < mesh->mNumFaces; i++)
|
||||
{
|
||||
aiFace face = mesh->mFaces[i];
|
||||
// Retrieve all indices of the face and store them in the indices vector
|
||||
for (GLuint j = 0; j < face.mNumIndices; j++)
|
||||
{
|
||||
indices.push_back(face.mIndices[j]);
|
||||
}
|
||||
}
|
||||
|
||||
// Process materials
|
||||
if (mesh->mMaterialIndex >= 0)
|
||||
{
|
||||
aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];
|
||||
// We assume a convention for sampler names in the shaders. Each diffuse texture should be named
|
||||
// as 'texture_diffuseN' where N is a sequential number ranging from 1 to MAX_SAMPLER_NUMBER.
|
||||
// Same applies to other texture as the following list summarizes:
|
||||
// Diffuse: texture_diffuseN
|
||||
// Specular: texture_specularN
|
||||
// Normal: texture_normalN
|
||||
|
||||
// 1. Diffuse maps
|
||||
vector<Texture> diffuseMaps = this->loadMaterialTextures(material, aiTextureType_DIFFUSE, "texture_diffuse");
|
||||
textures.insert(textures.end(), diffuseMaps.begin(), diffuseMaps.end());
|
||||
|
||||
// 2. Specular maps
|
||||
vector<Texture> specularMaps = this->loadMaterialTextures(material, aiTextureType_SPECULAR, "texture_specular");
|
||||
textures.insert(textures.end(), specularMaps.begin(), specularMaps.end());
|
||||
// 3. Normal maps
|
||||
vector<Texture> normalMaps = this->loadMaterialTextures(material, aiTextureType_HEIGHT, "texture_normal");
|
||||
textures.insert(textures.end(), normalMaps.begin(), normalMaps.end());
|
||||
}
|
||||
|
||||
// Return a mesh object created from the extracted mesh daata
|
||||
return Mesh(vertices, indices, textures);
|
||||
}
|
||||
|
||||
// Checks all material textures of a given type and loads the textures if they're not loaded yet.
|
||||
// The required info is returned as a Texture struct.
|
||||
vector<Texture> Model::loadMaterialTextures(aiMaterial* mat, aiTextureType type, string typeName)
|
||||
{
|
||||
vector<Texture> textures;
|
||||
int tmp = mat->GetTextureCount(type);
|
||||
//std::cout << tmp << endl;
|
||||
for (GLuint i = 0; i < tmp; i++)
|
||||
{
|
||||
aiString str;
|
||||
mat->GetTexture(type, i, &str);
|
||||
|
||||
// Check if texture was loaded before and if so, continue to next iteration: skip loading a new texture
|
||||
GLboolean skip = false;
|
||||
|
||||
for (GLuint j = 0; j < textures_loaded.size(); j++)
|
||||
{
|
||||
if (textures_loaded[j].path == str)
|
||||
{
|
||||
textures.push_back(textures_loaded[j]);
|
||||
skip = true; // A texture with the same filepath has already been loaded, continue to next one. (optimization)
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!skip)
|
||||
{ // If texture hasn't been loaded already, load it
|
||||
Texture texture;
|
||||
texture.id = TextureFromFile(str.C_Str(), this->directory);
|
||||
texture.type = typeName;
|
||||
texture.path = str;
|
||||
textures.push_back(texture);
|
||||
//std::cout << textures.size()<<endl;
|
||||
this->textures_loaded.push_back(texture); // Store it as texture loaded for entire model, to ensure we won't unnecesery load duplicate textures.
|
||||
}
|
||||
}
|
||||
|
||||
return textures;
|
||||
}
|
||||
|
||||
|
||||
GLint TextureFromFile(const char* path, string directory)
|
||||
{
|
||||
//Generate texture ID and load texture data
|
||||
string filename = string(path);
|
||||
filename = directory + "\\" + filename;
|
||||
GLuint textureID;
|
||||
glGenTextures(1, &textureID);
|
||||
|
||||
int width, height;
|
||||
|
||||
unsigned char* image = SOIL_load_image(filename.c_str(), &width, &height, 0, SOIL_LOAD_RGB);
|
||||
if (image == NULL)
|
||||
{
|
||||
std::cout << "error with loading image, by SOIL" << endl;
|
||||
}
|
||||
// Assign texture to ID
|
||||
glBindTexture(GL_TEXTURE_2D, textureID);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
|
||||
//std::cout << "GL ERRORS: " << glGetError();
|
||||
glGenerateMipmap(GL_TEXTURE_2D); //skalowanie szczegolow tekstury zalezne od polozenia kamery
|
||||
|
||||
// Parameters
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
SOIL_free_image_data(image);
|
||||
|
||||
return textureID;
|
||||
}
|
57
cw 6/src/Model.h
Normal file
@ -0,0 +1,57 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "glew.h"
|
||||
#include <glm.hpp>
|
||||
#include <gtc/matrix_transform.hpp>
|
||||
|
||||
#include "SOIL/SOIL.h"
|
||||
#include <assimp/Importer.hpp>
|
||||
#include <assimp/scene.h>
|
||||
#include <assimp/postprocess.h>
|
||||
#include <assimp/material.h>
|
||||
|
||||
#include "Texture.h"
|
||||
#include "Mesh.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
GLint TextureFromFile( const char *path, string directory );
|
||||
|
||||
class Model
|
||||
{
|
||||
public:
|
||||
/* Functions */
|
||||
// Constructor, expects a filepath to a 3D model.
|
||||
Model(GLchar* path);
|
||||
// Draws the model, and thus all its meshes
|
||||
void Draw(GLuint shader);
|
||||
vector<glm::vec3> getVertexPosition();
|
||||
|
||||
private:
|
||||
/* Model Data */
|
||||
vector<Mesh> meshes;
|
||||
string directory;
|
||||
vector<Texture> textures_loaded; // Stores all the textures loaded so far, optimization to make sure textures aren't loaded more than once.
|
||||
|
||||
/* Functions */
|
||||
// Loads a model with supported ASSIMP extensions from file and stores the resulting meshes in the meshes vector.
|
||||
void loadModel(string path);
|
||||
|
||||
// Processes a node in a recursive fashion. Processes each individual mesh located at the node and repeats this process on its children nodes (if any).
|
||||
void processNode(aiNode* node, const aiScene* scene);
|
||||
|
||||
Mesh processMesh(aiMesh* mesh, const aiScene* scene);
|
||||
|
||||
// Checks all material textures of a given type and loads the textures if they're not loaded yet.
|
||||
// The required info is returned as a Texture struct.
|
||||
vector<Texture> loadMaterialTextures(aiMaterial* mat, aiTextureType type, string typeName);
|
||||
};
|
||||
|
||||
|
98
cw 6/src/Shader.h
Normal file
@ -0,0 +1,98 @@
|
||||
#ifndef SHADER_H
|
||||
#define SHADER_H
|
||||
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
|
||||
#include "glew.h"
|
||||
|
||||
class Shader
|
||||
{
|
||||
public:
|
||||
GLuint Program;
|
||||
// Constructor generates the shader on the fly
|
||||
Shader( const GLchar *vertexPath, const GLchar *fragmentPath )
|
||||
{
|
||||
// 1. Retrieve the vertex/fragment source code from filePath
|
||||
std::string vertexCode;
|
||||
std::string fragmentCode;
|
||||
std::ifstream vShaderFile;
|
||||
std::ifstream fShaderFile;
|
||||
// ensures ifstream objects can throw exceptions:
|
||||
vShaderFile.exceptions ( std::ifstream::badbit );
|
||||
fShaderFile.exceptions ( std::ifstream::badbit );
|
||||
try
|
||||
{
|
||||
// Open files
|
||||
vShaderFile.open( vertexPath );
|
||||
fShaderFile.open( fragmentPath );
|
||||
std::stringstream vShaderStream, fShaderStream;
|
||||
// Read file's buffer contents into streams
|
||||
vShaderStream << vShaderFile.rdbuf( );
|
||||
fShaderStream << fShaderFile.rdbuf( );
|
||||
// close file handlers
|
||||
vShaderFile.close( );
|
||||
fShaderFile.close( );
|
||||
// Convert stream into string
|
||||
vertexCode = vShaderStream.str( );
|
||||
fragmentCode = fShaderStream.str( );
|
||||
}
|
||||
catch ( std::ifstream::failure e )
|
||||
{
|
||||
std::cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" << std::endl;
|
||||
}
|
||||
const GLchar *vShaderCode = vertexCode.c_str( );
|
||||
const GLchar *fShaderCode = fragmentCode.c_str( );
|
||||
// 2. Compile shaders
|
||||
GLuint vertex, fragment;
|
||||
GLint success;
|
||||
GLchar infoLog[512];
|
||||
// Vertex Shader
|
||||
vertex = glCreateShader( GL_VERTEX_SHADER );
|
||||
glShaderSource( vertex, 1, &vShaderCode, NULL );
|
||||
glCompileShader( vertex );
|
||||
// Print compile errors if any
|
||||
glGetShaderiv( vertex, GL_COMPILE_STATUS, &success );
|
||||
if ( !success )
|
||||
{
|
||||
glGetShaderInfoLog( vertex, 512, NULL, infoLog );
|
||||
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
|
||||
}
|
||||
// Fragment Shader
|
||||
fragment = glCreateShader( GL_FRAGMENT_SHADER );
|
||||
glShaderSource( fragment, 1, &fShaderCode, NULL );
|
||||
glCompileShader( fragment );
|
||||
// Print compile errors if any
|
||||
glGetShaderiv( fragment, GL_COMPILE_STATUS, &success );
|
||||
if ( !success )
|
||||
{
|
||||
glGetShaderInfoLog( fragment, 512, NULL, infoLog );
|
||||
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
|
||||
}
|
||||
// Shader Program
|
||||
this->Program = glCreateProgram( );
|
||||
glAttachShader( this->Program, vertex );
|
||||
glAttachShader( this->Program, fragment );
|
||||
glLinkProgram( this->Program );
|
||||
// Print linking errors if any
|
||||
glGetProgramiv( this->Program, GL_LINK_STATUS, &success );
|
||||
if (!success)
|
||||
{
|
||||
glGetProgramInfoLog( this->Program, 512, NULL, infoLog );
|
||||
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
|
||||
}
|
||||
// Delete the shaders as they're linked into our program now and no longer necessery
|
||||
glDeleteShader( vertex );
|
||||
glDeleteShader( fragment );
|
||||
|
||||
}
|
||||
// Uses the current shader
|
||||
void Use( )
|
||||
{
|
||||
glUseProgram( this->Program );
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
81
cw 6/src/Skybox.cpp
Normal file
@ -0,0 +1,81 @@
|
||||
#include "SOIL/SOIL.h"
|
||||
#include "glew.h"
|
||||
#include "freeglut.h"
|
||||
#include "glm.hpp"
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
unsigned int loadCubemap(std::vector<std::string> faces)
|
||||
{
|
||||
unsigned int textureID;
|
||||
glGenTextures(1, &textureID);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, textureID);
|
||||
|
||||
int width, height, nrChannels;
|
||||
for (unsigned int i = 0; i < faces.size(); i++) //looping over texture targets
|
||||
{
|
||||
//loading particular image
|
||||
unsigned char* data = SOIL_load_image(faces[i].c_str(), &width, &height, 0, SOIL_LOAD_RGB);
|
||||
|
||||
if (data)
|
||||
{
|
||||
//generating textures
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data); /// GL_TEXTURE_CUBE_MAP is linealy incremented
|
||||
SOIL_free_image_data(data);
|
||||
std::cout << "Cubemap texture loaded at some point to load at path: " << faces[i] << std::endl; //error
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Cubemap texture failed to load at path: " << faces[i] << std::endl; //error
|
||||
}
|
||||
}
|
||||
//setting texture parameters
|
||||
|
||||
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||
// This might help with seams on some systems
|
||||
glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
|
||||
return textureID;
|
||||
}
|
||||
|
||||
/*
|
||||
unsigned int LoadSkybox(unsigned int skyboxVAO, unsigned int skyboxVBO)
|
||||
{
|
||||
unsigned int cubemapTexture = loadCubemap(faces);
|
||||
glGenVertexArrays(1, &skyboxVAO);
|
||||
glGenBuffers(1, &skyboxVBO);
|
||||
glBindVertexArray(skyboxVAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, skyboxVBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxVertices), &skyboxVertices, GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindVertexArray(0);
|
||||
|
||||
return cubemapTexture;
|
||||
}
|
||||
*/
|
||||
|
||||
void drawSkyBox(glm::mat4 perspective, glm::mat4 view,GLuint programSkyBox, unsigned int skyboxVAO, unsigned int skyboxVBO,unsigned int cubemapTexture)
|
||||
{
|
||||
glDepthMask(GL_FALSE);
|
||||
glUseProgram(programSkyBox);
|
||||
glUniformMatrix4fv(glGetUniformLocation(programSkyBox, "view"), 1, GL_FALSE, (float*)&view);
|
||||
glUniformMatrix4fv(glGetUniformLocation(programSkyBox, "projection"), 1, GL_FALSE, (float*)&perspective);
|
||||
|
||||
// skybox cube
|
||||
glBindBuffer(GL_ARRAY_BUFFER, skyboxVBO);
|
||||
glBindVertexArray(skyboxVAO);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, cubemapTexture);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
glBindVertexArray(0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glUseProgram(0);
|
||||
glDepthMask(GL_TRUE);
|
||||
}
|
11
cw 6/src/Skybox.h
Normal file
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "SOIL/SOIL.h"
|
||||
#include "glew.h"
|
||||
#include "freeglut.h"
|
||||
#include "glm.hpp"
|
||||
|
||||
//unsigned int LoadSkybox(unsigned int skyboxVAO, unsigned int skyboxVBO);
|
||||
unsigned int loadCubemap(std::vector<std::string> faces);
|
||||
void drawSkyBox(glm::mat4 perspective, glm::mat4 view, GLuint programSkyBox, unsigned int skyboxVAO, unsigned int skyboxVBO, unsigned int cubemapTexture);
|
||||
|
@ -7,25 +7,24 @@
|
||||
#include <vector>
|
||||
#include <ctime>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "Shader_Loader.h"
|
||||
#include "Render_Utils.h"
|
||||
#include "Camera.h"
|
||||
#include "Texture.h"
|
||||
|
||||
#include "Bubble.h"
|
||||
|
||||
#include "Skybox.h"
|
||||
#include "SOIL/stb_image_aug.h"
|
||||
#include "Model.h"
|
||||
|
||||
|
||||
GLuint programColor;
|
||||
GLuint programTexture;
|
||||
|
||||
//GLuint skyboxTexture;
|
||||
Core::Shader_Loader shaderLoader;
|
||||
|
||||
Core::RenderContext sharkModel;
|
||||
Core::RenderContext sphereContext;
|
||||
|
||||
|
||||
glm::vec3 cameraPos = glm::vec3(0, 0, 5);
|
||||
glm::vec3 cameraDir; // Wektor "do przodu" kamery
|
||||
glm::vec3 cameraSide; // Wektor "w bok" kamery
|
||||
@ -39,9 +38,10 @@ glm::quat rotationX = glm::quat(1, 0, 0, 0);
|
||||
glm::quat rotationY = glm::quat(1, 0, 0, 0);
|
||||
glm::quat rotationZ = glm::quat(0, 0, 0, 0);
|
||||
std::vector<glm::vec3> planetsCoords;
|
||||
|
||||
glm::mat4 trans;
|
||||
std::vector<Bubble> bubbles;
|
||||
|
||||
|
||||
float mouseX = 0;
|
||||
float mouseY = 0;
|
||||
float prevX = 0;
|
||||
@ -49,6 +49,12 @@ float prevY = 0;
|
||||
|
||||
GLuint sharkTexture;
|
||||
|
||||
// SKYBOX
|
||||
unsigned int skyboxVAO, skyboxVBO;
|
||||
unsigned int cubemapTexture;
|
||||
GLuint testShader;
|
||||
GLuint programSkyBox;
|
||||
|
||||
float skyboxVertices[] = {
|
||||
// positions
|
||||
-1.0f, 1.0f, -1.0f,
|
||||
@ -94,6 +100,18 @@ float skyboxVertices[] = {
|
||||
1.0f, -1.0f, 1.0f
|
||||
};
|
||||
|
||||
|
||||
|
||||
std::vector<std::string> faces
|
||||
{
|
||||
"textures/right.jpg",
|
||||
"textures/left.jpg",
|
||||
"textures/top.jpg",
|
||||
"textures/bottom.jpg",
|
||||
"textures/front.jpg",
|
||||
"textures/back.jpg"
|
||||
};
|
||||
|
||||
void keyboard(unsigned char key, int x, int y)
|
||||
{
|
||||
|
||||
@ -110,6 +128,21 @@ void keyboard(unsigned char key, int x, int y)
|
||||
}
|
||||
}
|
||||
|
||||
// SKYBOX
|
||||
void loadSkybox()
|
||||
{
|
||||
cubemapTexture = loadCubemap(faces);
|
||||
glGenVertexArrays(1, &skyboxVAO);
|
||||
glGenBuffers(1, &skyboxVBO);
|
||||
glBindVertexArray(skyboxVAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, skyboxVBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxVertices), &skyboxVertices, GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
void mouse(int x, int y)
|
||||
{
|
||||
mouseX = x - prevX;
|
||||
@ -183,49 +216,41 @@ void drawBubbles()
|
||||
|
||||
}
|
||||
|
||||
|
||||
unsigned int loadCubemap(std::vector<std::string> faces)
|
||||
// SKYBOX
|
||||
void setUpUniforms(GLuint program, glm::mat4 modelMatrix)
|
||||
{
|
||||
unsigned int textureID;
|
||||
glGenTextures(1, &textureID);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, textureID);
|
||||
glUniform3f(glGetUniformLocation(program, "lightDir"), lightDir.x, lightDir.y, lightDir.z);
|
||||
glUniform3f(glGetUniformLocation(program, "cameraPos"), cameraPos.x, cameraPos.y, cameraPos.z);
|
||||
|
||||
int width, height, nrChannels;
|
||||
for (unsigned int i = 0; i < faces.size(); i++)
|
||||
{
|
||||
unsigned char* data = stbi_load(faces[i].c_str(), &width, &height, &nrChannels, 0);
|
||||
if (data)
|
||||
{
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i,
|
||||
0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data
|
||||
);
|
||||
stbi_image_free(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Cubemap tex failed to load at path: " << faces[i] << std::endl;
|
||||
stbi_image_free(data);
|
||||
}
|
||||
}
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||
|
||||
return textureID;
|
||||
glm::mat4 transformation = perspectiveMatrix * cameraMatrix * modelMatrix;
|
||||
glUniformMatrix4fv(glGetUniformLocation(program, "modelViewProjectionMatrix"), 1, GL_FALSE, (float*)&transformation);
|
||||
glUniformMatrix4fv(glGetUniformLocation(program, "modelMatrix"), 1, GL_FALSE, (float*)&modelMatrix);
|
||||
}
|
||||
|
||||
std::vector<std::string> faces =
|
||||
void drawObjectFromMesh(glm::mat4 modelMatrix, GLuint shader, int flag)
|
||||
{
|
||||
"textures/right.jpg",
|
||||
"textures/left.jpg",
|
||||
"textures/top.jpg",
|
||||
"textures/bottom.jpg",
|
||||
"textures/front.jpg",
|
||||
"textures/back.jpg"
|
||||
};
|
||||
unsigned int cubemapTexture = loadCubemap(faces);
|
||||
if (flag == 3)
|
||||
{
|
||||
GLuint program = shader;
|
||||
glm::vec3 color = glm::vec3(1.0f, 0.5f, 0.2f);
|
||||
glUseProgram(program);
|
||||
glUniform3f(glGetUniformLocation(program, "objectColor"), color.x, color.y, color.z);
|
||||
|
||||
glm::mat4 transformation = perspectiveMatrix * cameraMatrix * modelMatrix * trans;
|
||||
glUniformMatrix4fv(glGetUniformLocation(program, "transformation"), 1, GL_FALSE, (float*)&transformation);
|
||||
//glUniform3f(glGetUniformLocation(program, "lightDir"), lightDir[0], lightDir[1], lightDir[2]);
|
||||
glUniformMatrix4fv(glGetUniformLocation(program, "model"), 1, GL_FALSE, (float*)&modelMatrix);
|
||||
glUniform3f(glGetUniformLocation(program, "cameraPos"), cameraPos[0], cameraPos[1], cameraPos[2]);
|
||||
glUseProgram(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
GLuint program = shader;
|
||||
glUseProgram(program);
|
||||
setUpUniforms(program, modelMatrix);//modelMatrix pozycja poczatkowa
|
||||
glUseProgram(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void renderScene()
|
||||
@ -234,23 +259,22 @@ void renderScene()
|
||||
cameraMatrix = createCameraMatrix();
|
||||
perspectiveMatrix = Core::createPerspectiveMatrix();
|
||||
|
||||
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
glm::mat4 shipInitialTransformation = glm::translate(glm::vec3(0,-1.0f,-1.0f)) * glm::rotate(glm::radians(180.0f), glm::vec3(0,1,0)) * glm::scale(glm::vec3(0.25f));
|
||||
|
||||
|
||||
// SKYBOX
|
||||
glm::mat4 view = glm::mat4(glm::mat3(cameraMatrix));
|
||||
drawSkyBox(perspectiveMatrix, view, programSkyBox, skyboxVAO, skyboxVBO, cubemapTexture);
|
||||
//drawObjectFromMesh(shipModelMatrix, testShader, 1);
|
||||
glm::mat4 shipInitialTransformation = glm::translate(glm::vec3(0, -1.0f, -1.0f)) * glm::rotate(glm::radians(180.0f), glm::vec3(0, 1, 0)) * glm::scale(glm::vec3(0.25f));
|
||||
glm::mat4 shipModelMatrix = glm::translate(cameraPos + cameraDir * 0.5f) * glm::mat4_cast(glm::inverse(rotationX * rotationY * rotationZ)) * shipInitialTransformation;
|
||||
drawObjectTexture(sharkModel, shipModelMatrix, sharkTexture);
|
||||
|
||||
|
||||
drawObjectTexture(sharkModel, glm::mat4() * glm::scale(glm::vec3(0.25f)), sharkTexture);
|
||||
|
||||
drawBubbles();
|
||||
//drawObjectColor(sphereContext, glm::translate(glm::vec3(1.0f, 0.0f, 0.0f)), glm::vec4(0.0f, 0.0f, 1.0f, 0.3f));
|
||||
|
||||
//for (auto& coords : planetsCoords) {
|
||||
// drawObjectColor(sphereContext, glm::translate(coords), coords);
|
||||
//}
|
||||
|
||||
glutSwapBuffers();
|
||||
}
|
||||
|
||||
@ -283,28 +307,29 @@ void initBubbles() {
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void init()
|
||||
{
|
||||
srand(time(0));
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glEnable(GL_CULL_FACE);
|
||||
|
||||
|
||||
|
||||
programColor = shaderLoader.CreateProgram("shaders/shader_color.vert", "shaders/shader_color.frag");
|
||||
programTexture = shaderLoader.CreateProgram("shaders/shader_tex.vert", "shaders/shader_tex.frag");
|
||||
loadModelToContext("models/orca.obj", sharkModel);
|
||||
loadModelToContext("models/sphere.obj", sphereContext);
|
||||
sharkTexture = Core::LoadTexture("textures/Orca_Diffuse.jpg");
|
||||
initBubbles();
|
||||
|
||||
|
||||
|
||||
|
||||
testShader = shaderLoader.CreateProgram("shaders/shader_test.vert", "shaders/shader_test.frag");
|
||||
programSkyBox = shaderLoader.CreateProgram("shaders/shader_cube.vert", "shaders/shader_cube.frag");
|
||||
loadSkybox();
|
||||
programColor = shaderLoader.CreateProgram("shaders/shader_color.vert", "shaders/shader_color.frag");
|
||||
programTexture = shaderLoader.CreateProgram("shaders/shader_tex.vert", "shaders/shader_tex.frag");
|
||||
|
||||
loadModelToContext("models/orca.obj", sharkModel);
|
||||
loadModelToContext("models/sphere.obj", sphereContext);
|
||||
sharkTexture = Core::LoadTexture("textures/Orca_Diffuse.jpg");
|
||||
|
||||
initBubbles();
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
BIN
cw 6/textures/Underwater Box_Back.jpg
Normal file
After Width: | Height: | Size: 445 KiB |
BIN
cw 6/textures/Underwater Box_Bottom.jpg
Normal file
After Width: | Height: | Size: 433 KiB |
BIN
cw 6/textures/Underwater Box_Front.jpg
Normal file
After Width: | Height: | Size: 390 KiB |
BIN
cw 6/textures/Underwater Box_Left.jpg
Normal file
After Width: | Height: | Size: 387 KiB |
BIN
cw 6/textures/Underwater Box_Right.jpg
Normal file
After Width: | Height: | Size: 366 KiB |
BIN
cw 6/textures/Underwater Box_Top.jpg
Normal file
After Width: | Height: | Size: 292 KiB |
Before Width: | Height: | Size: 723 KiB After Width: | Height: | Size: 445 KiB |
Before Width: | Height: | Size: 274 KiB After Width: | Height: | Size: 433 KiB |
Before Width: | Height: | Size: 462 KiB After Width: | Height: | Size: 390 KiB |
Before Width: | Height: | Size: 588 KiB After Width: | Height: | Size: 387 KiB |
Before Width: | Height: | Size: 525 KiB After Width: | Height: | Size: 366 KiB |
Before Width: | Height: | Size: 338 KiB After Width: | Height: | Size: 292 KiB |