From 96a9c02a13d5a40de0538d369c97ca83022f20d6 Mon Sep 17 00:00:00 2001 From: kearwood Date: Fri, 23 Nov 2012 01:02:22 +0000 Subject: [PATCH] Implemented dust particle system --HG-- extra : convert_revision : svn%3A7752d6cf-9f14-4ad2-affc-04f1e67b81a5/trunk%40164 --- KREngine/KREngine/Classes/KRAABB.cpp | 6 ++ KREngine/KREngine/Classes/KRAABB.h | 1 + KREngine/KREngine/Classes/KRCamera.cpp | 2 + KREngine/KREngine/Classes/KRCamera.h | 2 + KREngine/KREngine/Classes/KRContext.cpp | 11 ++- KREngine/KREngine/Classes/KRContext.h | 6 +- KREngine/KREngine/Classes/KRContextObject.cpp | 2 +- KREngine/KREngine/Classes/KRContextObject.h | 2 +- .../KREngine/Classes/KRDirectionalLight.cpp | 2 +- KREngine/KREngine/Classes/KREngine.mm | 2 +- KREngine/KREngine/Classes/KRLight.cpp | 68 ++++++++++++++++++- KREngine/KREngine/Classes/KRLight.h | 7 +- KREngine/KREngine/Classes/KRModelManager.cpp | 40 ++++++----- KREngine/KREngine/Classes/KRModelManager.h | 3 +- KREngine/KREngine/Classes/KRShader.cpp | 8 +++ KREngine/KREngine/Classes/KRShader.h | 3 + KREngine/KREngine/Shaders/particle.fsh | 16 ++++- KREngine/KREngine/Shaders/particle.vsh | 21 +++++- KREngine/KREngine/Shaders/volumetric_fog.vsh | 2 +- 19 files changed, 165 insertions(+), 39 deletions(-) diff --git a/KREngine/KREngine/Classes/KRAABB.cpp b/KREngine/KREngine/Classes/KRAABB.cpp index e194c1f..89592cf 100644 --- a/KREngine/KREngine/Classes/KRAABB.cpp +++ b/KREngine/KREngine/Classes/KRAABB.cpp @@ -73,6 +73,12 @@ KRVector3 KRAABB::size() const return max - min; } +float KRAABB::volume() const +{ + KRVector3 s = size(); + return s.x * s.y * s.z; +} + void KRAABB::scale(const KRVector3 &s) { KRVector3 prev_center = center(); diff --git a/KREngine/KREngine/Classes/KRAABB.h b/KREngine/KREngine/Classes/KRAABB.h index 6fa461f..9d45ada 100644 --- a/KREngine/KREngine/Classes/KRAABB.h +++ b/KREngine/KREngine/Classes/KRAABB.h @@ -27,6 +27,7 @@ public: KRVector3 center() const; KRVector3 size() const; + float volume() const; bool intersects(const KRAABB& b) const; bool contains(const KRAABB &b) const; bool contains(const KRVector3 &v) const; diff --git a/KREngine/KREngine/Classes/KRCamera.cpp b/KREngine/KREngine/Classes/KRCamera.cpp index ee9d841..171a8ee 100644 --- a/KREngine/KREngine/Classes/KRCamera.cpp +++ b/KREngine/KREngine/Classes/KRCamera.cpp @@ -127,6 +127,8 @@ KRCamera::KRCamera(KRContext &context) : KRContextObject(context) { fog_density = 0.0005f; fog_color = KRVector3(0.45, 0.45, 0.5); fog_type = 0; + + dust_particle_intensity = 0.25f; } KRCamera::~KRCamera() { diff --git a/KREngine/KREngine/Classes/KRCamera.h b/KREngine/KREngine/Classes/KRCamera.h index 13752a2..01436d5 100644 --- a/KREngine/KREngine/Classes/KRCamera.h +++ b/KREngine/KREngine/Classes/KRCamera.h @@ -129,6 +129,8 @@ public: KRVector3 fog_color; int fog_type; // 0 = no fog, 1 = linear, 2 = exponential, 3 = exponential squared + float dust_particle_intensity; + private: KRVector3 m_position; diff --git a/KREngine/KREngine/Classes/KRContext.cpp b/KREngine/KREngine/Classes/KRContext.cpp index 6917745..8f3b128 100644 --- a/KREngine/KREngine/Classes/KRContext.cpp +++ b/KREngine/KREngine/Classes/KRContext.cpp @@ -35,6 +35,7 @@ KRContext::KRContext() { m_pSceneManager = new KRSceneManager(*this); m_bDetectedExtensions = false; m_current_frame = 0; + m_absolute_time = 0.0f; } KRContext::~KRContext() { @@ -147,14 +148,20 @@ void KRContext::startFrame() m_pTextureManager->startFrame(); } -void KRContext::endFrame() +void KRContext::endFrame(float deltaTime) { m_pTextureManager->endFrame(); rotateBuffers(true); m_current_frame++; + m_absolute_time += deltaTime; } -long KRContext::getCurrentFrame() +long KRContext::getCurrentFrame() const { return m_current_frame; } + +float KRContext::getAbsoluteTime() const +{ + return m_absolute_time; +} diff --git a/KREngine/KREngine/Classes/KRContext.h b/KREngine/KREngine/Classes/KRContext.h index da298f8..2b407be 100644 --- a/KREngine/KREngine/Classes/KRContext.h +++ b/KREngine/KREngine/Classes/KRContext.h @@ -57,9 +57,10 @@ public: static bool extension_available[KRENGINE_NUM_EXTENSIONS]; void startFrame(); - void endFrame(); + void endFrame(float deltaTime); - long getCurrentFrame(); + long getCurrentFrame() const; + float getAbsoluteTime() const; private: KRBundleManager *m_pBundleManager; @@ -73,6 +74,7 @@ private: bool m_bDetectedExtensions; long m_current_frame; + float m_absolute_time; }; #endif diff --git a/KREngine/KREngine/Classes/KRContextObject.cpp b/KREngine/KREngine/Classes/KRContextObject.cpp index 6fd88e7..cc24243 100644 --- a/KREngine/KREngine/Classes/KRContextObject.cpp +++ b/KREngine/KREngine/Classes/KRContextObject.cpp @@ -18,7 +18,7 @@ KRContextObject::~KRContextObject() } -KRContext &KRContextObject::getContext() +KRContext &KRContextObject::getContext() const { return *m_pContext; } \ No newline at end of file diff --git a/KREngine/KREngine/Classes/KRContextObject.h b/KREngine/KREngine/Classes/KRContextObject.h index 39c3c64..9e4d05e 100644 --- a/KREngine/KREngine/Classes/KRContextObject.h +++ b/KREngine/KREngine/Classes/KRContextObject.h @@ -17,7 +17,7 @@ public: KRContextObject(KRContext &context); ~KRContextObject(); - KRContext &getContext(); + KRContext &getContext() const; protected: KRContext *m_pContext; }; diff --git a/KREngine/KREngine/Classes/KRDirectionalLight.cpp b/KREngine/KREngine/Classes/KRDirectionalLight.cpp index 8472608..836c678 100644 --- a/KREngine/KREngine/Classes/KRDirectionalLight.cpp +++ b/KREngine/KREngine/Classes/KRDirectionalLight.cpp @@ -60,7 +60,7 @@ int KRDirectionalLight::configureShadowBufferViewports(const KRViewport &viewpor float min_depth = 0.0f; float max_depth = 1.0f; - KRAABB worldSpacefrustrumSliceBounds = KRAABB(KRVector3(-1.0f, -max_depth, -1.0f), KRVector3(1.0f, -min_depth, 1.0f), KRMat4::Invert(viewport.getViewProjectionMatrix())); + KRAABB worldSpacefrustrumSliceBounds = KRAABB(KRVector3(-1.0f, -1.0f, -1.0f), KRVector3(1.0f, 1.0f, 1.0f), KRMat4::Invert(viewport.getViewProjectionMatrix())); worldSpacefrustrumSliceBounds.scale(KRENGINE_SHADOW_BOUNDS_EXTRA_SCALE); KRVector3 shadowLook = -KRVector3::Normalize(getWorldLightDirection()); diff --git a/KREngine/KREngine/Classes/KREngine.mm b/KREngine/KREngine/Classes/KREngine.mm index 80c230b..dbf6af6 100644 --- a/KREngine/KREngine/Classes/KREngine.mm +++ b/KREngine/KREngine/Classes/KREngine.mm @@ -169,7 +169,7 @@ float const PI = 3.141592653589793f; { _context->startFrame(); _camera->renderFrame(*pScene, viewMatrix, deltaTime); - _context->endFrame(); + _context->endFrame(deltaTime); } - (BOOL)loadShaders diff --git a/KREngine/KREngine/Classes/KRLight.cpp b/KREngine/KREngine/Classes/KRLight.cpp index dd1a500..1776593 100644 --- a/KREngine/KREngine/Classes/KRLight.cpp +++ b/KREngine/KREngine/Classes/KRLight.cpp @@ -26,11 +26,15 @@ KRLight::KRLight(KRScene &scene, std::string name) : KRNode(scene, name) { m_intensity = 1.0f; + m_dust_particle_intensity = 1.0f; + m_color = KRVector3::One(); m_flareTexture = ""; m_pFlareTexture = NULL; m_flareSize = 0.0; m_casts_shadow = true; m_light_shafts = true; + m_dust_particle_density = 0.1f; + m_dust_particle_size = 1.0f; // Initialize shadow buffers m_cShadowBuffers = 0; @@ -58,12 +62,15 @@ tinyxml2::XMLElement *KRLight::saveXML( tinyxml2::XMLNode *parent) e->SetAttribute("flare_texture", m_flareTexture.c_str()); e->SetAttribute("casts_shadow", m_casts_shadow ? "true" : "false"); e->SetAttribute("light_shafts", m_light_shafts ? "true" : "false"); + e->SetAttribute("dust_particle_density", m_dust_particle_density); + e->SetAttribute("dust_particle_size", m_dust_particle_size); + e->SetAttribute("dust_particle_intensity", m_dust_particle_intensity); return e; } void KRLight::loadXML(tinyxml2::XMLElement *e) { KRNode::loadXML(e); - float x,y,z; + float x=1.0f,y=1.0f,z=1.0f; if(e->QueryFloatAttribute("color_r", &x) != tinyxml2::XML_SUCCESS) { x = 1.0; } @@ -95,6 +102,21 @@ void KRLight::loadXML(tinyxml2::XMLElement *e) { m_light_shafts = true; } + m_dust_particle_density = 0.1f; + if(e->QueryFloatAttribute("dust_particle_density", &m_dust_particle_density) != tinyxml2::XML_SUCCESS) { + m_dust_particle_density = 0.1f; + } + + m_dust_particle_size = 1.0f; + if(e->QueryFloatAttribute("dust_particle_size", &m_dust_particle_size) != tinyxml2::XML_SUCCESS) { + m_dust_particle_size = 1.0f; + } + + m_dust_particle_intensity = 1.0f; + if(e->QueryFloatAttribute("dust_particle_intensity", &m_dust_particle_intensity) != tinyxml2::XML_SUCCESS) { + m_dust_particle_intensity = 1.0f; + } + const char *szFlareTexture = e->Attribute("flare_texture"); if(szFlareTexture) { m_flareTexture = szFlareTexture; @@ -147,6 +169,46 @@ void KRLight::render(KRCamera *pCamera, std::vector &lights, const KR renderShadowBuffers(pCamera); } + if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES) { + // Render brownian particles for dust floating in air + if(m_cShadowBuffers >= 1 && shadowValid[0] && m_dust_particle_density > 0.0f && m_dust_particle_size > 0.0f && m_dust_particle_intensity > 0.0f) { + float lod_coverage = getBounds().coverage(viewport.getViewProjectionMatrix(), viewport.getSize()); // This also checks the view frustrum culling + if(lod_coverage > 0.0f || true) { + + float particle_range = 600.0f; + + int particle_count = m_dust_particle_density * pow(particle_range, 3); + if(particle_count > KRModelManager::KRENGINE_MAX_RANDOM_PARTICLES) particle_count = KRModelManager::KRENGINE_MAX_RANDOM_PARTICLES; + + // Enable z-buffer test + GLDEBUG(glEnable(GL_DEPTH_TEST)); + GLDEBUG(glDepthRangef(0.0, 1.0)); + + KRMat4 particleModelMatrix; + particleModelMatrix.scale(particle_range); // Scale the box symetrically to ensure that we don't have an uneven distribution of particles for different angles of the view frustrum + particleModelMatrix.translate(viewport.getCameraPosition()); + + std::vector this_light; + this_light.push_back(this); + + KRShader *pParticleShader = m_pContext->getShaderManager()->getShader("particle", pCamera, this_light, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass); + + if(getContext().getShaderManager()->selectShader(*pCamera, pParticleShader, viewport, particleModelMatrix, this_light, renderPass)) { + + (m_color * pCamera->dust_particle_intensity * m_dust_particle_intensity * m_intensity).setUniform(pParticleShader->m_uniforms[KRShader::KRENGINE_UNIFORM_LIGHT_COLOR]); + + KRMat4::DotWDiv(KRMat4::Invert(particleModelMatrix), KRVector3::Zero()).setUniform(pParticleShader->m_uniforms[KRShader::KRENGINE_UNIFORM_PARTICLE_ORIGIN]); + + GLDEBUG(glUniform1f(pParticleShader->m_uniforms[KRShader::KRENGINE_UNIFORM_FLARE_SIZE], m_dust_particle_size)); + + m_pContext->getModelManager()->bindVBO((void *)m_pContext->getModelManager()->getRandomParticles(), KRModelManager::KRENGINE_MAX_RANDOM_PARTICLES * 3 * sizeof(KRModelManager::RandomParticleVertexData), true, false, false, true, false); + GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, particle_count*3)); + } + } + } + } + + if(renderPass == KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE && pCamera->volumetric_environment_enable && m_light_shafts) { std::string shader_name = pCamera->volumetric_environment_downsample != 0 ? "volumetric_fog_downsampled" : "volumetric_fog"; @@ -164,9 +226,9 @@ void KRLight::render(KRCamera *pCamera, std::vector &lights, const KR float slice_spacing = (slice_far - slice_near) / slice_count; KRVector2(slice_near, slice_spacing).setUniform(pFogShader->m_uniforms[KRShader::KRENGINE_UNIFORM_SLICE_DEPTH_SCALE]); - (KRVector3::One() * pCamera->volumetric_environment_intensity * -slice_spacing / 1000.0f).setUniform(pFogShader->m_uniforms[KRShader::KRENGINE_UNIFORM_LIGHT_COLOR]); + (m_color * pCamera->volumetric_environment_intensity * m_intensity * -slice_spacing / 1000.0f).setUniform(pFogShader->m_uniforms[KRShader::KRENGINE_UNIFORM_LIGHT_COLOR]); - m_pContext->getModelManager()->bindVBO((void *)m_pContext->getModelManager()->getVolumetricLightingVertexes(), KRModelManager::MAX_VOLUMETRIC_PLANES * 6 * sizeof(KRModelManager::VolumetricLightingVertexData), true, false, false, false, false); + m_pContext->getModelManager()->bindVBO((void *)m_pContext->getModelManager()->getVolumetricLightingVertexes(), KRModelManager::KRENGINE_MAX_VOLUMETRIC_PLANES * 6 * sizeof(KRModelManager::VolumetricLightingVertexData), true, false, false, false, false); GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, slice_count*6)); } diff --git a/KREngine/KREngine/Classes/KRLight.h b/KREngine/KREngine/Classes/KRLight.h index b4cf91a..250f798 100644 --- a/KREngine/KREngine/Classes/KRLight.h +++ b/KREngine/KREngine/Classes/KRLight.h @@ -18,8 +18,8 @@ static const float KRLIGHT_MIN_INFLUENCE = 0.15f; // 0.05f // KRENGINE_MAX_SHADOW_BUFFERS must be at least 6 to allow omni-directional lights to render cube maps #define KRENGINE_MAX_SHADOW_BUFFERS 6 -#define KRENGINE_SHADOW_MAP_WIDTH 2048 -#define KRENGINE_SHADOW_MAP_HEIGHT 2048 +#define KRENGINE_SHADOW_MAP_WIDTH 1024 +#define KRENGINE_SHADOW_MAP_HEIGHT 1024 class KRLight : public KRNode { public: @@ -65,6 +65,9 @@ protected: bool m_casts_shadow; bool m_light_shafts; + float m_dust_particle_density; + float m_dust_particle_size; + float m_dust_particle_intensity; // Shadow Maps diff --git a/KREngine/KREngine/Classes/KRModelManager.cpp b/KREngine/KREngine/Classes/KRModelManager.cpp index 51e64c0..8ef33b7 100644 --- a/KREngine/KREngine/Classes/KRModelManager.cpp +++ b/KREngine/KREngine/Classes/KRModelManager.cpp @@ -255,9 +255,9 @@ void KRModelManager::rotateBuffers(bool new_frame) KRModelManager::VolumetricLightingVertexData *KRModelManager::getVolumetricLightingVertexes() { if(m_volumetricLightingVertexData == NULL) { - m_volumetricLightingVertexData = (VolumetricLightingVertexData *)malloc(sizeof(VolumetricLightingVertexData) * MAX_VOLUMETRIC_PLANES * 6); + m_volumetricLightingVertexData = (VolumetricLightingVertexData *)malloc(sizeof(VolumetricLightingVertexData) * KRENGINE_MAX_VOLUMETRIC_PLANES * 6); int iVertex=0; - for(int iPlane=0; iPlane < MAX_VOLUMETRIC_PLANES; iPlane++) { + for(int iPlane=0; iPlane < KRENGINE_MAX_VOLUMETRIC_PLANES; iPlane++) { m_volumetricLightingVertexData[iVertex].vertex.x = -1.0f; m_volumetricLightingVertexData[iVertex].vertex.y = -1.0f; m_volumetricLightingVertexData[iVertex].vertex.z = iPlane; @@ -300,31 +300,35 @@ KRModelManager::VolumetricLightingVertexData *KRModelManager::getVolumetricLight KRModelManager::RandomParticleVertexData *KRModelManager::getRandomParticles() { - const int MAX_PARTICLES=500000; if(m_randomParticleVertexData == NULL) { - m_randomParticleVertexData = (RandomParticleVertexData *)malloc(sizeof(RandomParticleVertexData) * MAX_PARTICLES * 3); + m_randomParticleVertexData = (RandomParticleVertexData *)malloc(sizeof(RandomParticleVertexData) * KRENGINE_MAX_RANDOM_PARTICLES * 3); + + // Generate vertices for randomly placed equilateral triangles with a side length of 1 and an origin point centered so that an inscribed circle can be efficiently rendered without wasting fill + + float equilateral_triangle_height = sqrt(3.0f) / 2.0f; + float inscribed_circle_radius = 1.0f / (2.0f * sqrt(3.0f)); int iVertex=0; - for(int iParticle=0; iParticle < MAX_PARTICLES; iParticle++) { - m_randomParticleVertexData[iVertex].vertex.x = (float)(arc4random() % 2000) / 1000.0f - 1.0f; - m_randomParticleVertexData[iVertex].vertex.y = (float)(arc4random() % 2000) / 1000.0f - 1.0f; - m_randomParticleVertexData[iVertex].vertex.z = (float)(arc4random() % 2000) / 1000.0f - 1.0f; - m_randomParticleVertexData[iVertex].uva.u = 0.0f; - m_randomParticleVertexData[iVertex].uva.v = 0.0f; - iVertex++; - - m_randomParticleVertexData[iVertex].vertex.x = m_randomParticleVertexData[iVertex-1].vertex.x; - m_randomParticleVertexData[iVertex].vertex.y = m_randomParticleVertexData[iVertex-1].vertex.y; - m_randomParticleVertexData[iVertex].vertex.z = m_randomParticleVertexData[iVertex-1].vertex.z; - m_randomParticleVertexData[iVertex].uva.u = 1.0f; - m_randomParticleVertexData[iVertex].uva.v = 0.0f; + for(int iParticle=0; iParticle < KRENGINE_MAX_RANDOM_PARTICLES; iParticle++) { + m_randomParticleVertexData[iVertex].vertex.x = (float)(arc4random() % 2000) / 1000.0f - 1000.0f; + m_randomParticleVertexData[iVertex].vertex.y = (float)(arc4random() % 2000) / 1000.0f - 1000.0f; + m_randomParticleVertexData[iVertex].vertex.z = (float)(arc4random() % 2000) / 1000.0f - 1000.0f; + m_randomParticleVertexData[iVertex].uva.u = -0.5f; + m_randomParticleVertexData[iVertex].uva.v = -inscribed_circle_radius; iVertex++; m_randomParticleVertexData[iVertex].vertex.x = m_randomParticleVertexData[iVertex-1].vertex.x; m_randomParticleVertexData[iVertex].vertex.y = m_randomParticleVertexData[iVertex-1].vertex.y; m_randomParticleVertexData[iVertex].vertex.z = m_randomParticleVertexData[iVertex-1].vertex.z; m_randomParticleVertexData[iVertex].uva.u = 0.5f; - m_randomParticleVertexData[iVertex].uva.v = 1.0f; + m_randomParticleVertexData[iVertex].uva.v = -inscribed_circle_radius; + iVertex++; + + m_randomParticleVertexData[iVertex].vertex.x = m_randomParticleVertexData[iVertex-1].vertex.x; + m_randomParticleVertexData[iVertex].vertex.y = m_randomParticleVertexData[iVertex-1].vertex.y; + m_randomParticleVertexData[iVertex].vertex.z = m_randomParticleVertexData[iVertex-1].vertex.z; + m_randomParticleVertexData[iVertex].uva.u = 0.0f; + m_randomParticleVertexData[iVertex].uva.v = -inscribed_circle_radius + equilateral_triangle_height; iVertex++; } } diff --git a/KREngine/KREngine/Classes/KRModelManager.h b/KREngine/KREngine/Classes/KRModelManager.h index 0818941..19ab78f 100644 --- a/KREngine/KREngine/Classes/KRModelManager.h +++ b/KREngine/KREngine/Classes/KRModelManager.h @@ -45,7 +45,8 @@ using std::map; class KRModelManager : public KRContextObject { public: - static const int MAX_VOLUMETRIC_PLANES=500; + static const int KRENGINE_MAX_VOLUMETRIC_PLANES=500; + static const int KRENGINE_MAX_RANDOM_PARTICLES=150000; KRModelManager(KRContext &context); virtual ~KRModelManager(); diff --git a/KREngine/KREngine/Classes/KRShader.cpp b/KREngine/KREngine/Classes/KRShader.cpp index 40462be..9b91918 100644 --- a/KREngine/KREngine/Classes/KRShader.cpp +++ b/KREngine/KREngine/Classes/KRShader.cpp @@ -180,6 +180,7 @@ KRShader::KRShader(KRContext &context, char *szKey, std::string options, std::st GLDEBUG(m_uniforms[KRENGINE_UNIFORM_GBUFFER_DEPTH] = glGetUniformLocation(m_iProgram, "gbuffer_depth")); GLDEBUG(m_uniforms[KRENGINE_UNIFORM_DEPTH_FRAME] = glGetUniformLocation(m_iProgram, "depthFrame")); GLDEBUG(m_uniforms[KRENGINE_UNIFORM_RENDER_FRAME] = glGetUniformLocation(m_iProgram, "renderFrame")); + GLDEBUG(m_uniforms[KRENGINE_UNIFORM_ABSOLUTE_TIME] = glGetUniformLocation(m_iProgram, "time_absolute")); GLDEBUG(m_uniforms[KRENGINE_UNIFORM_SLICE_DEPTH_SCALE] = glGetUniformLocation(m_iProgram, "slice_depth_scale")); GLDEBUG(m_uniforms[KRENGINE_UNIFORM_VOLUMETRIC_ENVIRONMENT_FRAME] = glGetUniformLocation(m_iProgram, "volumetricEnvironmentFrame")); @@ -192,6 +193,9 @@ KRShader::KRShader(KRContext &context, char *szKey, std::string options, std::st GLDEBUG(m_uniforms[KRENGINE_UNIFORM_FOG_SCALE] = glGetUniformLocation(m_iProgram, "fog_scale")); GLDEBUG(m_uniforms[KRENGINE_UNIFORM_DENSITY_PREMULTIPLIED_EXPONENTIAL] = glGetUniformLocation(m_iProgram, "fog_density_premultiplied_exponential")); GLDEBUG(m_uniforms[KRENGINE_UNIFORM_DENSITY_PREMULTIPLIED_SQUARED] = glGetUniformLocation(m_iProgram, "fog_density_premultiplied_squared")); + + + GLDEBUG(m_uniforms[KRENGINE_UNIFORM_PARTICLE_ORIGIN] = glGetUniformLocation(m_iProgram, "particle_origin")); } @@ -233,8 +237,12 @@ bool KRShader::bind(KRCamera &camera, const KRViewport &viewport, const KRMat4 & return false; } + + GLDEBUG(glUseProgram(m_iProgram)); + GLDEBUG(glUniform1f(m_uniforms[KRENGINE_UNIFORM_ABSOLUTE_TIME], getContext().getAbsoluteTime())); + int light_directional_count = 0; int light_point_count = 0; int light_spot_count = 0; diff --git a/KREngine/KREngine/Classes/KRShader.h b/KREngine/KREngine/Classes/KRShader.h index 0b287b6..b58c5b3 100644 --- a/KREngine/KREngine/Classes/KRShader.h +++ b/KREngine/KREngine/Classes/KRShader.h @@ -128,6 +128,7 @@ public: KRENGINE_UNIFORM_DEPTH_FRAME, KRENGINE_UNIFORM_VOLUMETRIC_ENVIRONMENT_FRAME, KRENGINE_UNIFORM_RENDER_FRAME, + KRENGINE_UNIFORM_ABSOLUTE_TIME, KRENGINE_UNIFORM_FOG_NEAR, KRENGINE_UNIFORM_FOG_FAR, @@ -140,6 +141,8 @@ public: KRENGINE_UNIFORM_SLICE_DEPTH_SCALE, + KRENGINE_UNIFORM_PARTICLE_ORIGIN, + KRENGINE_NUM_UNIFORMS }; GLint m_uniforms[KRENGINE_NUM_UNIFORMS]; diff --git a/KREngine/KREngine/Shaders/particle.fsh b/KREngine/KREngine/Shaders/particle.fsh index 8a887d5..fdb0654 100644 --- a/KREngine/KREngine/Shaders/particle.fsh +++ b/KREngine/KREngine/Shaders/particle.fsh @@ -29,10 +29,20 @@ // or implied, of Kearwood Gilbert. // +#extension GL_EXT_shadow_samplers : require + varying mediump vec2 texCoord; -uniform sampler2D diffuseTexture; + +varying mediump vec4 shadowMapCoord1; +uniform sampler2DShadow shadowTexture1; +uniform mediump vec3 light_color; +varying lowp float intensity_modulate; void main() { - gl_FragColor = vec4(vec3(texture2D(diffuseTexture, texCoord)), 1.0); - //gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); + //gl_FragColor = vec4(vec3(texture2D(diffuseTexture, texCoord)), 1.0); +// gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); + gl_FragColor = vec4(light_color, 1.0) * shadow2DProjEXT(shadowTexture1, shadowMapCoord1) * max(1.0 - texCoord.x*texCoord.x-texCoord.y*texCoord.y, 0.0) * intensity_modulate; +// gl_FragColor.rgb = shadowMapCoord1.xyz / shadowMapCoord1.w; +// gl_FragColor.a = 1.0; +// gl_FragColor.b = 1.0; } \ No newline at end of file diff --git a/KREngine/KREngine/Shaders/particle.vsh b/KREngine/KREngine/Shaders/particle.vsh index 4b851b5..29db6d0 100644 --- a/KREngine/KREngine/Shaders/particle.vsh +++ b/KREngine/KREngine/Shaders/particle.vsh @@ -34,10 +34,25 @@ uniform highp mat4 mvp_matrix; // mvp_matrix is the result of multiplying t uniform mediump vec4 viewport; uniform mediump float flare_size; attribute vec4 vertex_position; +uniform highp vec3 particle_origin; -varying mediump vec2 texCoord; +uniform highp mat4 shadow_mvp1; +varying mediump vec4 shadowMapCoord1; + +varying mediump vec2 texCoord; +uniform highp float time_absolute; +varying lowp float intensity_modulate; void main() { - texCoord = vertex_uv; - gl_Position = mvp_matrix * vertex_position + vec4(vertex_uv.x * viewport.w / viewport.z * 2.0 - 1.0, vertex_uv.y * 2.0 - 1.0, 0.0, 0.0) * flare_size; +// highp vec4 particle_center = mvp_matrix * (mod(vertex_position - vec4(particle_origin, 0.0), 2.0) - 1.0); + highp vec4 offset_center = vertex_position + vec4(particle_origin, 0.0); + offset_center.xyz += vec3(sin((time_absolute + vertex_position.x * 100.0) * 0.05), sin((time_absolute + vertex_position.y * 100.0) * 0.07), sin((time_absolute + vertex_position.z * 100.0) * 0.03)) * 0.05; + offset_center = vec4(mod(offset_center.x + 1.0, 2.0) - 1.0, mod(offset_center.y + 1.0, 2.0) - 1.0, mod(offset_center.z + 1.0, 2.0) - 1.0, 1.0); + highp vec4 particle_center = mvp_matrix * offset_center; + texCoord = vertex_uv * 3.46410161513775; // 3.46410161513775 = 2 * sqrt(3); 1 / (2 * sqrt(3)) is the radius of a circle encompased by a equilateral triangle with a side length of 1. + gl_Position = particle_center + vec4(vertex_uv.x * viewport.w / viewport.z * 2.0 - 1.0, vertex_uv.y * 2.0 - 1.0, 0.0, 0.0) * flare_size; + + shadowMapCoord1 = shadow_mvp1 * offset_center; + + intensity_modulate = sin(time_absolute + mod(vertex_position.x * 100.0, 6.28318530717959)) * 0.5 + 0.5; } diff --git a/KREngine/KREngine/Shaders/volumetric_fog.vsh b/KREngine/KREngine/Shaders/volumetric_fog.vsh index 5c1bb40..2f98b72 100644 --- a/KREngine/KREngine/Shaders/volumetric_fog.vsh +++ b/KREngine/KREngine/Shaders/volumetric_fog.vsh @@ -30,7 +30,7 @@ uniform highp mat4 inv_mvp_matrix; uniform highp vec2 slice_depth_scale; // First component is the depth for the nearest plane, in view space. Second component is the distance between planes, in view space -uniform highp mat4 shadow_mvp1; +uniform highp mat4 shadow_mvp1; varying mediump vec4 shadowMapCoord1; uniform highp mat4 projection_matrix;