experiments with shaders

This commit is contained in:
VB
2017-03-19 10:48:22 +01:00
parent 3941283381
commit 4d19e49398
20 changed files with 381 additions and 191 deletions

View File

@@ -106,3 +106,6 @@ target_link_libraries(${PROJECT_NAME} ${PYTHON_LIBRARIES})
find_package(PNG REQUIRED)
include_directories(${PNG_INCLUDE_DIRS})
target_link_libraries(${PROJECT_NAME} ${PNG_LIBRARIES})
find_package(GLM REQUIRED)
include_directories(${GLM_INCLUDE_DIRS})

View File

@@ -0,0 +1,52 @@
#
# Find GLM
#
# Try to find GLM : OpenGL Mathematics.
# This module defines
# - GLM_INCLUDE_DIRS
# - GLM_FOUND
#
# The following variables can be set as arguments for the module.
# - GLM_ROOT_DIR : Root library directory of GLM
#
# References:
# - https://github.com/Groovounet/glm/blob/master/util/FindGLM.cmake
# - https://bitbucket.org/alfonse/gltut/src/28636298c1c0/glm-0.9.0.7/FindGLM.cmake
#
# Additional modules
include(FindPackageHandleStandardArgs)
if (WIN32)
# Find include files
find_path(
GLM_INCLUDE_DIR
NAMES glm/glm.hpp
PATHS
$ENV{PROGRAMFILES}/include
${GLM_ROOT_DIR}/include
DOC "The directory where glm/glm.hpp resides")
else()
# Find include files
find_path(
GLM_INCLUDE_DIR
NAMES glm/glm.hpp
PATHS
/usr/include
/usr/local/include
/sw/include
/opt/local/include
${GLM_ROOT_DIR}/include
DOC "The directory where glm/glm.hpp resides")
endif()
# Handle REQUIRD argument, define *_FOUND variable
find_package_handle_standard_args(GLM DEFAULT_MSG GLM_INCLUDE_DIR)
# Define GLM_INCLUDE_DIRS
if (GLM_FOUND)
set(GLM_INCLUDE_DIRS ${GLM_INCLUDE_DIR})
endif()
# Hide some variables
mark_as_advanced(GLM_INCLUDE_DIR)

View File

@@ -231,6 +231,8 @@ int main(int argc, char *argv[])
glfwWindowHint(GLFW_AUTO_ICONIFY, GLFW_FALSE);
glfwWindowHint(GLFW_SAMPLES, 1 << Global::iMultisampling);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
if (Global::bFullScreen)
{
@@ -279,11 +281,19 @@ int main(int argc, char *argv[])
GfxRenderer.Init();
Global::pWorld = &World; // Ra: wskaźnik potrzebny do usuwania pojazdów
try
{
if (!World.Init(window))
{
std::cout << "failed to init TWorld" << std::endl;
return -1;
}
}
catch (std::runtime_error e)
{
WriteLog(e.what());
return -1;
}
Console *pConsole = new Console(); // Ra: nie wiem, czy ma to sens, ale jakoś zainicjowac trzeba

View File

@@ -103,8 +103,7 @@ GLfloat Global::ambientLight[] = {0.80f, 0.80f, 0.85f, 1.0f}; // stałe
GLfloat Global::diffuseLight[] = {0.85f, 0.85f, 0.80f, 1.0f};
GLfloat Global::specularLight[] = {0.95f, 0.94f, 0.90f, 1.0f};
#else
opengl_light Global::DayLight;
int Global::DynamicLightCount{ 3 };
int Global::DynamicLightCount = 7;
#endif
GLfloat Global::whiteLight[] = {1.00f, 1.00f, 1.00f, 1.0f};
GLfloat Global::noLight[] = {0.00f, 0.00f, 0.00f, 1.0f};
@@ -220,6 +219,8 @@ double Global::fMWDamp[2] = { 800, 1023 };
double Global::fMWDlowVolt[2] = { 150, 1023 };
int Global::iMWDdivider = 5;
Global::daylight_s Global::daylight;
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------

View File

@@ -234,7 +234,6 @@ class Global
static GLfloat specularLight[];
#else
// TODO: put these things in the renderer
static opengl_light DayLight;
static int DynamicLightCount;
#endif
static GLfloat whiteLight[];
@@ -366,5 +365,15 @@ class Global
static double fMWDamp[2];
static double fMWDlowVolt[2];
static int iMWDdivider;
struct daylight_s
{
float3 position;
float3 direction;
float3 color;
float3 ambient;
};
static daylight_s daylight;
};
//---------------------------------------------------------------------------

View File

@@ -339,9 +339,9 @@ void TGroundNode::RenderVBO()
g = floor( Diffuse[ 1 ] * Global::ambientDayLight[ 1 ] );
b = floor( Diffuse[ 2 ] * Global::ambientDayLight[ 2 ] );
#else
r = floor( Diffuse[ 0 ] * Global::DayLight.ambient[ 0 ] ); // w zaleznosci od koloru swiatla
g = floor( Diffuse[ 1 ] * Global::DayLight.ambient[ 1 ] );
b = floor( Diffuse[ 2 ] * Global::DayLight.ambient[ 2 ] );
r = floor( Diffuse[ 0 ] * Global::daylight.ambient.x ); // w zaleznosci od koloru swiatla
g = floor( Diffuse[ 1 ] * Global::daylight.ambient.y );
b = floor( Diffuse[ 2 ] * Global::daylight.ambient.z );
#endif
glColor4ub(r, g, b, linealpha); // przezroczystosc dalekiej linii
// glDisable(GL_LIGHTING); //nie powinny świecić
@@ -405,9 +405,9 @@ void TGroundNode::RenderAlphaVBO()
g = Diffuse[ 1 ] * Global::ambientDayLight[ 1 ];
b = Diffuse[ 2 ] * Global::ambientDayLight[ 2 ];
#else
r = Diffuse[ 0 ] * Global::DayLight.ambient[ 0 ]; // w zaleznosci od koloru swiatla
g = Diffuse[ 1 ] * Global::DayLight.ambient[ 1 ];
b = Diffuse[ 2 ] * Global::DayLight.ambient[ 2 ];
r = Diffuse[ 0 ] * Global::daylight.ambient.x; // w zaleznosci od koloru swiatla
g = Diffuse[ 1 ] * Global::daylight.ambient.y;
b = Diffuse[ 2 ] * Global::daylight.ambient.z;
#endif
glColor4ub(r, g, b, linealpha); // przezroczystosc dalekiej linii
// glDisable(GL_LIGHTING); //nie powinny świecić
@@ -605,9 +605,9 @@ void TGroundNode::RenderDL()
g = Diffuse[ 1 ] * Global::ambientDayLight[ 1 ];
b = Diffuse[ 2 ] * Global::ambientDayLight[ 2 ];
#else
r = Diffuse[ 0 ] * Global::DayLight.ambient[ 0 ]; // w zaleznosci od koloru swiatla
g = Diffuse[ 1 ] * Global::DayLight.ambient[ 1 ];
b = Diffuse[ 2 ] * Global::DayLight.ambient[ 2 ];
r = Diffuse[ 0 ] * Global::daylight.ambient.x; // w zaleznosci od koloru swiatla
g = Diffuse[ 1 ] * Global::daylight.ambient.y;
b = Diffuse[ 2 ] * Global::daylight.ambient.z;
#endif
glColor4ub(r, g, b, 1.0);
glCallList(DisplayListID);
@@ -686,9 +686,9 @@ void TGroundNode::RenderAlphaDL()
g = Diffuse[ 1 ] * Global::ambientDayLight[ 1 ];
b = Diffuse[ 2 ] * Global::ambientDayLight[ 2 ];
#else
r = Diffuse[ 0 ] * Global::DayLight.ambient[ 0 ]; // w zaleznosci od koloru swiatla
g = Diffuse[ 1 ] * Global::DayLight.ambient[ 1 ];
b = Diffuse[ 2 ] * Global::DayLight.ambient[ 2 ];
r = Diffuse[ 0 ] * Global::daylight.ambient.x; // w zaleznosci od koloru swiatla
g = Diffuse[ 1 ] * Global::daylight.ambient.y;
b = Diffuse[ 2 ] * Global::daylight.ambient.z;
#endif
glColor4ub(r, g, b, linealpha); // przezroczystosc dalekiej linii
glCallList(DisplayListID);
@@ -2877,10 +2877,9 @@ bool TGround::Init(std::string File)
#else
parser.getTokens(3, false);
parser
>> Global::DayLight.direction.x
>> Global::DayLight.direction.y
>> Global::DayLight.direction.z;;
Global::DayLight.direction.Normalize();
>> Global::daylight.direction.x
>> Global::daylight.direction.y
>> Global::daylight.direction.z;
#endif
parser.getTokens(9, false);
@@ -2901,7 +2900,7 @@ bool TGround::Init(std::string File)
// kolor wszechobceny
>> Global::DayLight.ambient[0]
>> Global::DayLight.ambient[1]
>> Global::DayLight.ambient[2]
>> Global::daylight.ambient.z
// kolor padający
>> Global::DayLight.diffuse[0]
>> Global::DayLight.diffuse[1]

View File

@@ -308,7 +308,8 @@ class TGround
event_map m_eventmap;
TNames<TGroundNode *> m_trackmap;
#endif
light_array m_lights; // collection of dynamic light sources present in the scene
light_array m_lights;
private: // metody prywatne
bool EventConditon(TEvent *e);

View File

@@ -23,6 +23,10 @@ Copyright (C) 2001-2004 Marcin Wozniak, Maciej Czapkiewicz and others
#include "Timer.h"
#include "mtable.h"
#include "sn_utils.h"
#include "World.h"
extern TWorld World;
//---------------------------------------------------------------------------
using namespace Mtable;
@@ -1243,6 +1247,7 @@ void TSubModel::RenderVBO()
if (b_Anim)
RaAnimation(b_Anim);
}
World.shader.copy_gl_mvp();
if (eType < TP_ROTATOR)
{ // renderowanie obiektów OpenGL
if (iAlpha & iFlags & 0x1F) // rysuj gdy element nieprzezroczysty
@@ -1418,6 +1423,7 @@ void TSubModel::RenderAlphaVBO()
if (b_aAnim)
RaAnimation(b_aAnim);
}
World.shader.copy_gl_mvp();
glColor3fv(f4Diffuse);
if (eType < TP_ROTATOR)
{ // renderowanie obiektów OpenGL

View File

@@ -2463,7 +2463,6 @@ void TTrack::RaRenderVBO(int iPtr)
// dla kolejnych tekstur!
EnvironmentSet();
int seg;
int i;
switch (iCategoryFlag & 15)
{
case 1: // tor

View File

@@ -328,9 +328,9 @@ void TTraction::RenderDL(float mgn) // McZapkie: mgn to odleglosc od obserwatora
g *= Global::ambientDayLight[ 1 ];
b *= Global::ambientDayLight[ 2 ];
#else
r *= Global::DayLight.ambient[ 0 ]; // w zaleźności od koloru swiatła
g *= Global::DayLight.ambient[ 1 ];
b *= Global::DayLight.ambient[2];
r *= Global::daylight.ambient.x; // w zaleźności od koloru swiatła
g *= Global::daylight.ambient.y;
b *= Global::daylight.ambient.z;
#endif
if (linealpha > 1.0f)
linealpha = 1.0f; // trzeba ograniczyć do <=1
@@ -538,9 +538,9 @@ void TTraction::RenderVBO(float mgn, int iPtr)
g *= Global::ambientDayLight[ 1 ];
b *= Global::ambientDayLight[ 2 ];
#else
r *= Global::DayLight.ambient[ 0 ]; // w zaleźności od koloru swiatła
g *= Global::DayLight.ambient[ 1 ];
b *= Global::DayLight.ambient[ 2 ];
r *= Global::daylight.ambient.x; // w zaleźności od koloru swiatła
g *= Global::daylight.ambient.y;
b *= Global::daylight.ambient.z;
#endif
if (linealpha > 1.0f)
linealpha = 1.0f; // trzeba ograniczyć do <=1

46
VBO.cpp
View File

@@ -12,6 +12,7 @@ http://mozilla.org/MPL/2.0/.
#include "GL/glew.h"
#include "usefull.h"
#include "sn_utils.h"
#include "World.h"
//---------------------------------------------------------------------------
void CVertNormTex::deserialize(std::istream &s)
@@ -64,10 +65,18 @@ void CMesh::BuildVBOs(bool del)
{ // tworzenie VBO i kasowanie już niepotrzebnych tablic
// pobierz numer VBO oraz ustaw go jako aktywny
glGenBuffers(1, &m_nVBOVertices); // pobierz numer
glBindBuffer(GL_ARRAY_BUFFER, m_nVBOVertices); // ustaw bufor jako aktualny
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, m_nVBOVertices);
glBufferData(GL_ARRAY_BUFFER, m_nVertexCount * sizeof(CVertNormTex), m_pVNT, GL_STATIC_DRAW);
// WriteLog("Assigned VBO number "+AnsiString(m_nVBOVertices)+", vertices:
// "+AnsiString(m_nVertexCount));
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 8, (GLvoid*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 8, (GLvoid*)(sizeof(float) * 3));
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 8, (GLvoid*)(sizeof(float) * 6));
glEnableVertexAttribArray(2);
glBindVertexArray(0);
if (del)
SafeDeleteArray(m_pVNT); // wierzchołki już się nie przydadzą
};
@@ -77,33 +86,32 @@ void CMesh::Clear()
// inna nazwa, żeby nie mieszało się z funkcją wirtualną sprzątacza
if (m_nVBOVertices) // jeśli było coś rezerwowane
{
glDeleteBuffers(1, &m_nVBOVertices); // Free The Memory
// WriteLog("Released VBO number "+AnsiString(m_nVBOVertices));
glDeleteBuffers(1, &m_nVBOVertices);
glDeleteVertexArrays(1, &vao);
}
m_nVBOVertices = 0;
m_nVertexCount = -1; // do ponownego zliczenia
SafeDeleteArray(m_pVNT); // usuwanie tablic, gdy były użyte do Vertex Array
};
extern TWorld World;
bool CMesh::StartVBO()
{ // początek rysowania elementów z VBO
if (m_nVertexCount <= 0)
return false; // nie ma nic do rysowania w ten sposób
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
if (m_nVBOVertices)
{
glBindBuffer(GL_ARRAY_BUFFER_ARB, m_nVBOVertices);
glVertexPointer( 3, GL_FLOAT, sizeof(CVertNormTex), static_cast<char *>(nullptr) ); // pozycje
glNormalPointer( GL_FLOAT, sizeof( CVertNormTex ), static_cast<char *>( nullptr ) + 12 ); // normalne
glTexCoordPointer( 2, GL_FLOAT, sizeof( CVertNormTex ), static_cast<char *>( nullptr ) + 24 ); // wierzchołki
}
glBindVertexArray(vao);
glUseProgram(World.shader);
World.shader.copy_gl_mvp();
return true; // można rysować z VBO
};
bool CMesh::StartColorVBO()
{ // początek rysowania punktów świecących z VBO
return false; //m7todo
/*
if (m_nVertexCount <= 0)
return false; // nie ma nic do rysowania w ten sposób
glEnableClientState(GL_VERTEX_ARRAY);
@@ -116,15 +124,11 @@ bool CMesh::StartColorVBO()
glColorPointer( 3, GL_FLOAT, sizeof( CVertNormTex ), static_cast<char *>( nullptr ) + 12 ); // kolory
}
return true; // można rysować z VBO
*/
};
void CMesh::EndVBO()
{ // koniec użycia VBO
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
// glBindBuffer(GL_ARRAY_BUFFER,0); //takie coś psuje, mimo iż polecali użyć
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); // Ra: to na przyszłość
glBindVertexArray(0);
glUseProgram(0);
};

4
VBO.h
View File

@@ -7,6 +7,8 @@ obtain one at
http://mozilla.org/MPL/2.0/.
*/
#include "shader.h"
#ifndef VBOH
#define VBOH
//---------------------------------------------------------------------------
@@ -28,6 +30,8 @@ class CVertNormTex
class CMesh
{ // wsparcie dla VBO
GLuint vao;
gl_program shader;
public:
int m_nVertexCount; // liczba wierzchołków
CVertNormTex *m_pVNT;

View File

@@ -186,7 +186,7 @@ bool TWorld::Init(GLFWwindow *w)
WriteLog(glver);
if (!GLEW_VERSION_1_4)
{
std::cout << "required opengl >=1.4" << std::endl;
std::cout << "required opengl >=3.2" << std::endl;
return false;
}
@@ -249,6 +249,9 @@ bool TWorld::Init(GLFWwindow *w)
WriteLog("Max texture size: " + std::to_string(Global::iMaxTextureSize));
}
/*-----------------------Render Initialization----------------------*/
shader = gl_program_light({gl_shader("lighting.vert"), gl_shader("blinnphong.frag")});
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glMatrixMode( GL_MODELVIEW );
@@ -453,15 +456,13 @@ bool TWorld::Init(GLFWwindow *w)
GLfloat ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f };
::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, ambient );
Global::DayLight.id = opengl_renderer::sunlight;
// directional light
// TODO, TBD: test omni-directional variant
Global::DayLight.position[ 3 ] = 1.0f;
::glLightf( opengl_renderer::sunlight, GL_SPOT_CUTOFF, 90.0 );
// rgb value for 5780 kelvin
Global::DayLight.diffuse[ 0 ] = 255.0f / 255.0f;
Global::DayLight.diffuse[ 1 ] = 242.0f / 255.0f;
Global::DayLight.diffuse[ 2 ] = 231.0f / 255.0f;
Global::daylight.color.x = 255.0f / 255.0f;
Global::daylight.color.y = 242.0f / 255.0f;
Global::daylight.color.z = 231.0f / 255.0f;
#endif
Ground.Init(Global::SceneryFile);
@@ -2925,6 +2926,7 @@ void TWorld::CabChange(TDynamicObject *old, TDynamicObject *now)
void
world_environment::init() {
m_skydome.init();
m_sun.init();
m_stars.init();
m_clouds.Init();
@@ -2938,8 +2940,6 @@ world_environment::update() {
auto const position = m_sun.getPosition();
// ...update the global data to match new sun state...
Global::SunAngle = m_sun.getAngle();
Global::DayLight.set_position( position );
Global::DayLight.direction = -1.0 * m_sun.getDirection();
// ...update skydome to match the current sun position as well...
m_skydome.Update( position );
// ...retrieve current sky colour and brightness...
@@ -2950,15 +2950,14 @@ world_environment::update() {
// NOTE: intensity combines intensity of the sun and the light reflected by the sky dome
// it'd be more technically correct to have just the intensity of the sun here,
// but whether it'd _look_ better is something to be tested
Global::DayLight.diffuse[ 0 ] = intensity * 255.0f / 255.0f;
Global::DayLight.diffuse[ 1 ] = intensity * 242.0f / 255.0f;
Global::DayLight.diffuse[ 2 ] = intensity * 231.0f / 255.0f;
Global::DayLight.ambient[ 0 ] = skydomecolour.x;
Global::DayLight.ambient[ 1 ] = skydomecolour.y;
Global::DayLight.ambient[ 2 ] = skydomecolour.z;
Global::fLuminance = intensity;
Global::daylight.position = float3(position.x, position.y, position.z);
vector3 sun = -1.0 * m_sun.getDirection();
Global::daylight.direction = float3(sun.x, sun.y, sun.z);
Global::daylight.color = float3(intensity * 255.0f / 255.0f,
intensity * 242.0f / 255.0f,
intensity * 231.0f / 255.0f);
Global::daylight.ambient = float3(skydomecolour.x, skydomecolour.y, skydomecolour.z);
// update the fog. setting it to match the average colour of the sky dome is cheap
// but quite effective way to make the distant items blend with background better
@@ -2970,6 +2969,8 @@ world_environment::update() {
::glClearColor( skydomecolour.x, skydomecolour.y, skydomecolour.z, 1.0f ); // kolor nieba
}
extern TWorld World;
void
world_environment::render() {
@@ -2990,8 +2991,9 @@ world_environment::render() {
// mark sun position for easier debugging
m_sun.render();
}
Global::DayLight.apply_angle();
Global::DayLight.apply_intensity();
World.shader.set_ambient(Global::daylight.ambient);
World.shader.set_light(0, gl_program_light::DIR, Global::daylight.position, Global::daylight.direction, 0.0f, 0.0f, Global::daylight.color, 0.0f, 0.0f);
::glPopMatrix();
::glDepthMask( GL_TRUE );

View File

@@ -89,10 +89,13 @@ class TWorld
int tprev; // poprzedni czas
double Acc; // przyspieszenie styczne
bool m_init{ false }; // indicates whether initial update of the world was performed
public:
void ModifyTGA(std::string const &dir = "");
void CreateE3D(std::string const &dir = "", bool dyn = false);
void CabChange(TDynamicObject *old, TDynamicObject *now);
gl_program_light shader; //m7todo: tmp
};
//---------------------------------------------------------------------------

View File

@@ -10,39 +10,27 @@ http://mozilla.org/MPL/2.0/.
#include "stdafx.h"
#include "renderer.h"
#include "globals.h"
#include "World.h"
opengl_renderer GfxRenderer;
extern TWorld World;
void
opengl_renderer::Init() {
// create dynamic light pool
for( int idx = 0; idx < Global::DynamicLightCount; ++idx ) {
opengl_light light;
light.id = GL_LIGHT1 + idx;
light.position[ 3 ] = 1.0f;
::glLightf( light.id, GL_SPOT_CUTOFF, 7.5f );
::glLightf( light.id, GL_SPOT_EXPONENT, 7.5f );
::glLightf( light.id, GL_CONSTANT_ATTENUATION, 0.0f );
::glLightf( light.id, GL_LINEAR_ATTENUATION, 0.035f );
m_lights.emplace_back( light );
}
}
void
opengl_renderer::Update_Lights( light_array const &Lights ) {
size_t const count = std::min( m_lights.size(), Lights.data.size() );
size_t const count = std::min( (size_t)Global::DynamicLightCount, Lights.data.size() );
if( count == 0 ) { return; }
auto renderlight = m_lights.begin();
size_t renderlight = 0;
for( auto const &scenelight : Lights.data ) {
if( renderlight == m_lights.end() ) {
if( renderlight == Global::DynamicLightCount ) {
// we ran out of lights to assign
break;
}
@@ -55,40 +43,27 @@ opengl_renderer::Update_Lights( light_array const &Lights ) {
// but there could still be weaker lights which are closer, so keep looking
continue;
}
// if the light passed tests so far, it's good enough
renderlight->set_position( scenelight.position );
renderlight->direction = scenelight.direction;
auto const luminance = Global::fLuminance; // TODO: adjust this based on location, e.g. for tunnels
renderlight->diffuse[ 0 ] = std::max( 0.0, scenelight.color.x - luminance );
renderlight->diffuse[ 1 ] = std::max( 0.0, scenelight.color.y - luminance );
renderlight->diffuse[ 2 ] = std::max( 0.0, scenelight.color.z - luminance );
renderlight->ambient[ 0 ] = std::max( 0.0, scenelight.color.x * scenelight.intensity - luminance);
renderlight->ambient[ 1 ] = std::max( 0.0, scenelight.color.y * scenelight.intensity - luminance );
renderlight->ambient[ 2 ] = std::max( 0.0, scenelight.color.z * scenelight.intensity - luminance );
float3 position(scenelight.position.x, scenelight.position.y, scenelight.position.z);
float3 direction(scenelight.direction.x, scenelight.direction.y, scenelight.direction.z);
float3 color(scenelight.color.x,
scenelight.color.y,
scenelight.color.z);
::glLightf( renderlight->id, GL_LINEAR_ATTENUATION, (0.25f * scenelight.count) / std::pow( scenelight.count, 2 ) );
::glEnable( renderlight->id );
renderlight->apply_intensity();
renderlight->apply_angle();
World.shader.set_light((GLuint)renderlight + 1, gl_program_light::SPOT, position, direction, 0.906f, 0.866f, color, 0.007f, 0.0002f);
++renderlight;
}
while( renderlight != m_lights.end() ) {
// if we went through all scene lights and there's still opengl lights remaining, kill these
::glDisable( renderlight->id );
++renderlight;
}
World.shader.set_light_count((GLuint)renderlight + 1);
}
void
opengl_renderer::Disable_Lights() {
for( size_t idx = 0; idx < m_lights.size() + 1; ++idx ) {
::glDisable( GL_LIGHT0 + (int)idx );
}
World.shader.set_light_count(0);
}
//---------------------------------------------------------------------------

View File

@@ -14,47 +14,6 @@ http://mozilla.org/MPL/2.0/.
#include "lightarray.h"
#include "dumb3d.h"
struct opengl_light {
GLuint id{ (GLuint)-1 };
Math3D::vector3 direction;
GLfloat position[ 4 ]; // 4th parameter specifies directional(0) or omni-directional(1) light source
GLfloat ambient[ 4 ];
GLfloat diffuse[ 4 ];
GLfloat specular[ 4 ];
opengl_light() {
position[ 0 ] = position[ 1 ] = position[ 2 ] = 0.0f; position[ 3 ] = 1.0f; // 0,0,0,1
ambient[ 0 ] = ambient[ 1 ] = ambient[ 2 ] = 0.0f; ambient[ 3 ] = 1.0f; // 0,0,0,1
diffuse[ 0 ] = diffuse[ 1 ] = diffuse[ 2 ] = diffuse[ 3 ] = 1.0f; // 1,1,1,1
specular[ 0 ] = specular[ 1 ] = specular[ 2 ] = specular[ 3 ] = 1.0f; // 1,1,1,1
}
inline
void apply_intensity() {
glLightfv( id, GL_AMBIENT, ambient );
glLightfv( id, GL_DIFFUSE, diffuse );
glLightfv( id, GL_SPECULAR, specular );
}
inline
void apply_angle() {
glLightfv( id, GL_POSITION, position );
if( position[ 3 ] == 1.0f ) {
GLfloat directionarray[] = { (GLfloat)direction.x, (GLfloat)direction.y, (GLfloat)direction.z };
glLightfv( id, GL_SPOT_DIRECTION, directionarray );
}
}
inline
void set_position( Math3D::vector3 const &Position ) {
position[ 0 ] = Position.x;
position[ 1 ] = Position.y;
position[ 2 ] = Position.z;
}
};
// encapsulates basic rendering setup.
// for modern opengl this translates to a specific collection of glsl shaders,
// for legacy opengl this is combination of blending modes, active texture units etc
@@ -104,7 +63,7 @@ public:
}
// members
GLenum static const sunlight{ GL_LIGHT0 };
GLenum static const sunlight{ 0 };
private:
// types
@@ -112,11 +71,8 @@ private:
color
};
typedef std::vector<opengl_light> opengllight_array;
// members
rendermode renderpass{ rendermode::color };
opengllight_array m_lights;
texture_manager m_textures;
};

View File

@@ -4,6 +4,12 @@
#include "stdafx.h"
#include "shader.h"
#include "Float3d.h"
#include "Logs.h"
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
inline bool strcend(std::string const &value, std::string const &ending)
{
@@ -14,6 +20,8 @@ inline bool strcend(std::string const &value, std::string const &ending)
gl_shader::gl_shader(std::string filename)
{
WriteLog("loading shader " + filename + " ..", false);
std::stringstream stream;
std::ifstream f;
f.exceptions(std::ifstream::badbit);
@@ -48,13 +56,20 @@ gl_shader::gl_shader(std::string filename)
glGetShaderInfoLog(id, 512, 0, info);
throw std::runtime_error("failed to compile " + filename + ": " + std::string(info));
}
WriteLog("done.");
}
gl_shader::operator GLuint()
{
return id;
}
gl_program::gl_program(std::vector<gl_shader> shaders)
{
id = glCreateProgram();
for (auto s : shaders)
glAttachShader(id, s.id);
glAttachShader(id, s);
glLinkProgram(id);
GLint status;
@@ -67,7 +82,79 @@ gl_program::gl_program(std::vector<gl_shader> shaders)
}
}
void gl_program::use()
gl_program::operator GLuint()
{
return id;
}
gl_program_mvp::gl_program_mvp(std::vector<gl_shader> v) : gl_program(v)
{
mv_uniform = glGetUniformLocation(id, "modelview");
p_uniform = glGetUniformLocation(id, "projection");
}
void gl_program_mvp::copy_gl_mvp()
{
float4x4 mv, p;
glGetFloatv(GL_MODELVIEW_MATRIX, mv.e);
glGetFloatv(GL_PROJECTION_MATRIX, p.e);
glUniformMatrix4fv(mv_uniform, 1, GL_FALSE, mv.e);
glUniformMatrix4fv(p_uniform, 1, GL_FALSE, p.e);
}
gl_program_light::gl_program_light(std::vector<gl_shader> v) : gl_program_mvp(v)
{
ambient_uniform = glGetUniformLocation(id, "ambient");
lcount_uniform = glGetUniformLocation(id, "lights_count");
for (size_t i = 0; i < MAX_LIGHTS; i++)
{
lights_uniform[i].type = glGetUniformLocation(id, std::string("lights[" + std::to_string(i) + "].type").c_str());
lights_uniform[i].pos = glGetUniformLocation(id, std::string("lights[" + std::to_string(i) + "].pos").c_str());
lights_uniform[i].dir = glGetUniformLocation(id, std::string("lights[" + std::to_string(i) + "].dir").c_str());
lights_uniform[i].in_cutoff = glGetUniformLocation(id, std::string("lights[" + std::to_string(i) + "].in_cutoff").c_str());
lights_uniform[i].out_cutoff = glGetUniformLocation(id, std::string("lights[" + std::to_string(i) + "].out_cutoff").c_str());
lights_uniform[i].color = glGetUniformLocation(id, std::string("lights[" + std::to_string(i) + "].color").c_str());
lights_uniform[i].linear = glGetUniformLocation(id, std::string("lights[" + std::to_string(i) + "].linear").c_str());
lights_uniform[i].quadratic = glGetUniformLocation(id, std::string("lights[" + std::to_string(i) + "].quadratic").c_str());
}
glUseProgram(id);
glUniform3f(ambient_uniform, 1.0f, 1.0f, 1.0f);
glUniform1i(lcount_uniform, 0);
}
void gl_program_light::set_ambient(float3 &ambient)
{
glUseProgram(id);
glUniform3fv(ambient_uniform, 1, &ambient.x);
}
void gl_program_light::set_light_count(GLuint count)
{
glUseProgram(id);
glUniform1ui(lcount_uniform, count);
}
void gl_program_light::set_light(GLuint i, type t, float3 &pos, float3 &dir,
float in_cutoff, float out_cutoff,
float3 &color, float linear, float quadratic)
{
float arr[16];
glGetFloatv(GL_MODELVIEW_MATRIX, arr);
glm::mat4 mv = glm::make_mat4(arr);
glm::vec3 trans_pos = mv * glm::vec4(pos.x, pos.y, pos.z, 1.0f);
glm::vec3 trans_dir = mv * glm::vec4(dir.x, dir.y, dir.z, 0.0f);
glUseProgram(id);
glUniform1ui(lights_uniform[i].type, (GLuint)t);
glUniform3fv(lights_uniform[i].pos, 1, glm::value_ptr(trans_pos));
glUniform3fv(lights_uniform[i].dir, 1, glm::value_ptr(trans_dir));
glUniform1f(lights_uniform[i].in_cutoff, in_cutoff);
glUniform1f(lights_uniform[i].out_cutoff, out_cutoff);
glUniform3fv(lights_uniform[i].color, 1, &color.x);
glUniform1f(lights_uniform[i].linear, linear);
glUniform1f(lights_uniform[i].quadratic, quadratic);
}

View File

@@ -2,21 +2,74 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#pragma once
#include "Float3d.h"
class gl_shader
{
public:
GLuint id;
public:
gl_shader();
gl_shader(std::string);
operator GLuint();
};
class gl_program
{
protected:
GLuint id;
public:
gl_program() = default;
gl_program(std::vector<gl_shader>);
void use();
operator GLuint();
};
class gl_program_mvp : public gl_program
{
GLuint mv_uniform;
GLuint p_uniform;
public:
gl_program_mvp() = default;
gl_program_mvp(std::vector<gl_shader>);
void copy_gl_mvp();
};
class gl_program_light : public gl_program_mvp
{
public:
static const size_t MAX_LIGHTS = 8;
enum type
{
SPOT = 0,
POINT,
DIR
};
gl_program_light() = default;
gl_program_light(std::vector<gl_shader>);
void set_ambient(float3 &ambient);
void set_light_count(GLuint count);
void set_light(GLuint id, type t, float3 &pos, float3 &dir, float in_cutoff, float out_cutoff,
float3 &color, float linear, float quadratic);
private:
GLuint lcount_uniform;
GLuint ambient_uniform;
struct light_s
{
GLuint type;
GLuint pos;
GLuint dir;
GLuint in_cutoff;
GLuint out_cutoff;
GLuint color;
GLuint linear;
GLuint quadratic;
} lights_uniform[MAX_LIGHTS];
};

View File

@@ -1,9 +1,10 @@
#include "stdafx.h"
#include "skydome.h"
#include "color.h"
#include "usefull.h"
#include "Globals.h"
// sky gradient based on "A practical analytic model for daylight"
// by A. J. Preetham Peter Shirley Brian Smits (University of Utah)
@@ -42,20 +43,34 @@ float CSkyDome::m_zenithymatrix[ 3 ][ 4 ] = {
//******************************************************************************//
CSkyDome::CSkyDome (int const Tesselation) :
m_tesselation( Tesselation ) {
float clamp( float const Value, float const Min, float const Max ) {
float value = Value;
if( value < Min ) { value = Min; }
if( value > Max ) { value = Max; }
return value;
}
float interpolate( float const First, float const Second, float const Factor ) {
return ( First * ( 1.0f - Factor ) ) + ( Second * Factor );
}
//******************************************************************************//
void CSkyDome::init(int const Tesselation)
{
m_tesselation = Tesselation;
// SetSunPosition( Math3D::vector3(75.0f, 0.0f, 0.0f) );
SetTurbidity(3.0f);
SetExposure(true, 20.0f);
SetOvercastFactor(0.05f);
SetGammaCorrection(2.2f);
m_shader = gl_program_mvp({ gl_shader("color.frag"),
gl_shader("vbocolor.vert") });
Generate();
}
CSkyDome::~CSkyDome() {
}
//******************************************************************************//
void CSkyDome::Generate() {
@@ -118,7 +133,7 @@ void CSkyDome::Update( Math3D::vector3 const &Sun ) {
// render skydome to screen
void CSkyDome::Render() {
if( m_vertexbuffer == -1 ) {
if( m_vao == -1 ) {
// build the buffers
::glGenBuffers( 1, &m_vertexbuffer );
::glBindBuffer( GL_ARRAY_BUFFER, m_vertexbuffer );
@@ -131,23 +146,30 @@ void CSkyDome::Render() {
::glGenBuffers( 1, &m_indexbuffer );
::glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, m_indexbuffer );
::glBufferData( GL_ELEMENT_ARRAY_BUFFER, m_indices.size() * sizeof( unsigned short ), m_indices.data(), GL_STATIC_DRAW );
glGenVertexArrays(1, &m_vao);
glBindVertexArray(m_vao);
glBindBuffer(GL_ARRAY_BUFFER, m_vertexbuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_indexbuffer);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float3), 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, m_coloursbuffer);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float3), 0);
glEnableVertexAttribArray(1);
glBindVertexArray(0);
// NOTE: vertex and index source data is superfluous past this point, but, eh
}
// begin
::glEnableClientState( GL_VERTEX_ARRAY );
::glEnableClientState( GL_COLOR_ARRAY );
// positions
::glBindBuffer( GL_ARRAY_BUFFER, m_vertexbuffer );
::glVertexPointer( 3, GL_FLOAT, sizeof( float3 ), reinterpret_cast<void const*>( 0 ) );
// colours
::glBindBuffer( GL_ARRAY_BUFFER, m_coloursbuffer );
::glColorPointer( 3, GL_FLOAT, sizeof( float3 ), reinterpret_cast<void const*>( 0 ) );
// indices
::glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, m_indexbuffer );
::glDrawElements( GL_TRIANGLES, static_cast<GLsizei>( m_indices.size() ), GL_UNSIGNED_SHORT, reinterpret_cast<void const*>( 0 ) );
// cleanup
::glDisableClientState( GL_COLOR_ARRAY );
::glDisableClientState( GL_VERTEX_ARRAY );
glUseProgram(m_shader);
glBindVertexArray(m_vao);
m_shader.copy_gl_mvp();
glDrawElements(GL_TRIANGLES, (GLsizei)m_indices.size(), GL_UNSIGNED_SHORT, 0);
glBindVertexArray(0);
glUseProgram(0);
}
bool CSkyDome::SetSunPosition( Math3D::vector3 const &Direction ) {

View File

@@ -2,14 +2,15 @@
#include "dumb3d.h"
#include "float3d.h"
#include "shader.h"
// sky gradient based on "A practical analytic model for daylight"
// by A. J. Preetham Peter Shirley Brian Smits (University of Utah)
class CSkyDome {
public:
CSkyDome( int const Tesselation = 54 );
~CSkyDome();
void init(int const Tesselation = 54);
void Generate();
void RebuildColors();
@@ -39,8 +40,10 @@ private:
float m_gammacorrection;
float3 m_averagecolour;
gl_program_mvp m_shader;
// data
int const m_tesselation;
int m_tesselation;
std::vector<float3> m_vertices;
std::vector<std::uint16_t> m_indices;
// std::vector<float3> m_normals;
@@ -48,6 +51,7 @@ private:
GLuint m_vertexbuffer{ (GLuint)-1 };
GLuint m_indexbuffer{ (GLuint)-1 };
GLuint m_coloursbuffer{ (GLuint)-1 };
GLuint m_vao = (GLuint)-1;
static float m_distributionluminance[ 5 ][ 2 ];
static float m_distributionxcomp[ 5 ][ 2 ];