mirror of
https://bitbucket.org/CPMADevs/cnq3
synced 2024-11-10 06:31:48 +00:00
afc81437c3
- added the foundation for a GPU particle system - reworked volumetric particle injection
210 lines
5.1 KiB
C++
210 lines
5.1 KiB
C++
/*
|
|
===========================================================================
|
|
Copyright (C) 2024 Gian 'myT' Schellenbaum
|
|
|
|
This file is part of Challenge Quake 3 (CNQ3).
|
|
|
|
Challenge Quake 3 is free software; you can redistribute it
|
|
and/or modify it under the terms of the GNU General Public License as
|
|
published by the Free Software Foundation; either version 2 of the License,
|
|
or (at your option) any later version.
|
|
|
|
Challenge Quake 3 is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with Challenge Quake 3. If not, see <https://www.gnu.org/licenses/>.
|
|
===========================================================================
|
|
*/
|
|
// Cinematic Rendering Pipeline - sunlight editor
|
|
|
|
|
|
#include "crp_local.h"
|
|
#include "../client/cl_imgui.h"
|
|
#include "compshaders/crp/fullscreen.h"
|
|
#include "compshaders/crp/sun_overlay.h"
|
|
|
|
|
|
#pragma pack(push, 4)
|
|
struct SunOverlayRC
|
|
{
|
|
vec3_t direction;
|
|
float angle;
|
|
vec3_t color;
|
|
float padding;
|
|
float textureWidth;
|
|
float textureHeight;
|
|
};
|
|
#pragma pack(pop)
|
|
|
|
|
|
static bool LoadSunFile(const char* filePath)
|
|
{
|
|
bool success = false;
|
|
void* data = NULL;
|
|
if(ri.FS_ReadFile(filePath, &data) == sizeof(crp.sunlightData) &&
|
|
data != NULL)
|
|
{
|
|
memcpy(&crp.sunlightData, data, sizeof(crp.sunlightData));
|
|
success = true;
|
|
}
|
|
if(data != NULL)
|
|
{
|
|
ri.FS_FreeFile(data);
|
|
}
|
|
|
|
return success;
|
|
}
|
|
|
|
static void SaveSunFile(const char* filePath)
|
|
{
|
|
FS_EnableCNQ3FolderWrites(qtrue);
|
|
ri.FS_WriteFile(filePath, &crp.sunlightData, sizeof(crp.sunlightData));
|
|
FS_EnableCNQ3FolderWrites(qfalse);
|
|
}
|
|
|
|
static void LoadSunFromShader(const shader_t* skyShader)
|
|
{
|
|
vec2_t angles;
|
|
angles[0] = DEG2RAD(skyShader->sunAzimuth);
|
|
angles[1] = DEG2RAD(skyShader->sunInclination);
|
|
VectorCopy(skyShader->sunColor, crp.sunlightData.color);
|
|
AzimuthInclinationToDirection(crp.sunlightData.direction, angles);
|
|
}
|
|
|
|
void DirectionToAzimuthInclination(float* sc, const float* dir)
|
|
{
|
|
// 0=azimuth/phi, 1=inclination/theta
|
|
sc[0] = atan2f(dir[1], dir[0]);
|
|
sc[1] = atan2f(sqrtf(dir[0] * dir[0] + dir[1] * dir[1]), dir[2]);
|
|
}
|
|
|
|
void AzimuthInclinationToDirection(float* dir, const float* sc)
|
|
{
|
|
// 0=azimuth/phi, 1=inclination/theta
|
|
dir[0] = sinf(sc[1]) * cosf(sc[0]);
|
|
dir[1] = sinf(sc[1]) * sinf(sc[0]);
|
|
dir[2] = cosf(sc[1]);
|
|
}
|
|
|
|
|
|
void SunlightEditor::Init()
|
|
{
|
|
{
|
|
GraphicsPipelineDesc desc("G-Buffer Depth");
|
|
MakeFullScreenPipeline(desc, ShaderByteCode(g_sun_overlay_ps));
|
|
desc.AddRenderTarget(GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA, crp.renderTargetFormat);
|
|
pipeline = CreateGraphicsPipeline(desc);
|
|
}
|
|
}
|
|
|
|
void SunlightEditor::ProcessWorld(world_t& world)
|
|
{
|
|
skyShader = NULL;
|
|
for(int i = 0; i < tr.numShaders; i++)
|
|
{
|
|
if(tr.shaders[i]->isSunDataValid)
|
|
{
|
|
skyShader = tr.shaders[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(!LoadSunFile(va("sun/%s.sun", world.baseName)) &&
|
|
skyShader != NULL)
|
|
{
|
|
LoadSunFromShader(skyShader);
|
|
}
|
|
}
|
|
|
|
void SunlightEditor::DrawOverlay()
|
|
{
|
|
if(!drawOverlay || !IsViewportFullscreen(backEnd.viewParms))
|
|
{
|
|
return;
|
|
}
|
|
|
|
srp.renderMode = RenderMode::None;
|
|
|
|
SCOPED_RENDER_PASS("Sun Overlay", 1.0f, 1.0f, 1.0f);
|
|
|
|
CmdSetViewportAndScissor(0, 0, glConfig.vidWidth, glConfig.vidHeight);
|
|
|
|
CmdBeginBarrier();
|
|
CmdTextureBarrier(crp.renderTarget, ResourceStates::RenderTargetBit);
|
|
CmdEndBarrier();
|
|
|
|
SunOverlayRC rc = {};
|
|
rc.angle = 0.0f;
|
|
VectorCopy(crp.sunlightData.color, rc.color);
|
|
VectorCopy(crp.sunlightData.direction, rc.direction);
|
|
rc.textureWidth = glConfig.vidWidth;
|
|
rc.textureHeight = glConfig.vidHeight;
|
|
|
|
CmdBindRenderTargets(1, &crp.renderTarget, NULL);
|
|
CmdBindPipeline(pipeline);
|
|
CmdSetGraphicsRootConstants(0, sizeof(rc), &rc);
|
|
CmdDraw(3, 0);
|
|
}
|
|
|
|
void SunlightEditor::DrawGUI()
|
|
{
|
|
if(tr.world == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
GUI_AddMainMenuItem(GUI_MainMenu::Tools, "Edit Sunlight", "", &windowActive);
|
|
|
|
if(!windowActive)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if(ImGui::Begin("Sunlight", &windowActive, ImGuiWindowFlags_AlwaysAutoResize))
|
|
{
|
|
ImGui::Checkbox("Draw Sun", &drawOverlay);
|
|
|
|
float angles[2];
|
|
DirectionToAzimuthInclination(angles, crp.sunlightData.direction);
|
|
ImGui::NewLine();
|
|
ImGui::SliderAngle("Azimuth", &angles[0], 0.0f, 360.0f);
|
|
ImGui::SliderAngle("Inclination", &angles[1], 0.0f, 180.0f);
|
|
AzimuthInclinationToDirection(crp.sunlightData.direction, angles);
|
|
ImGui::ColorEdit3("Color", crp.sunlightData.color);
|
|
ImGui::SliderFloat("Light intensity in fog/smoke", &crp.sunlightData.intensityVL, 0.0f, 200.0f);
|
|
ImGui::SliderFloat("Light intensity on surfaces", &crp.sunlightData.intensityDL, 0.0f, 10.0f);
|
|
|
|
ImGui::NewLine();
|
|
if(ImGui::Button("Save Config..."))
|
|
{
|
|
SaveFileDialog_Open("sun", ".sun");
|
|
}
|
|
ImGui::SameLine();
|
|
if(ImGui::Button("Open Config..."))
|
|
{
|
|
OpenFileDialog_Open("sun", ".sun");
|
|
}
|
|
if(skyShader != NULL)
|
|
{
|
|
ImGui::SameLine();
|
|
if(ImGui::Button("Import from Sky Shader"))
|
|
{
|
|
LoadSunFromShader(skyShader);
|
|
}
|
|
}
|
|
|
|
if(SaveFileDialog_Do())
|
|
{
|
|
SaveSunFile(SaveFileDialog_GetPath());
|
|
}
|
|
|
|
if(OpenFileDialog_Do())
|
|
{
|
|
LoadSunFile(OpenFileDialog_GetPath());
|
|
}
|
|
}
|
|
ImGui::End();
|
|
}
|