forked from Patoke/4JLibs
feat: better cmake support (#21)
* feat: CMakeSettings.json * chore: remove visual studio stuff chore: move .clang-format to main directory * feat: new file structure, easier to implement as a submodule within existing projects * chore: we actually include some code now... * chore: remove prebuilt libraries (oops) * feat: new shader building script using cmake * chore: add debug postfix specifier * fix: forgot that windows builds use 4J_Render_PC for the render library * fix: didn't add the output directory (where shaders are saved to) to the include directories of 4J_Render
This commit is contained in:
@@ -0,0 +1,503 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2026 Patoke
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "4J_Render.h"
|
||||
#include "Renderer.h"
|
||||
|
||||
C4JRender RenderManager;
|
||||
|
||||
void C4JRender::Tick()
|
||||
{
|
||||
InternalRenderManager.CBuffTick();
|
||||
}
|
||||
|
||||
void C4JRender::UpdateGamma(unsigned short usGamma)
|
||||
{
|
||||
InternalRenderManager.UpdateGamma(usGamma);
|
||||
}
|
||||
|
||||
void C4JRender::MatrixMode(int type)
|
||||
{
|
||||
InternalRenderManager.MatrixMode(type);
|
||||
}
|
||||
|
||||
void C4JRender::MatrixSetIdentity()
|
||||
{
|
||||
InternalRenderManager.MatrixSetIdentity();
|
||||
}
|
||||
|
||||
void C4JRender::MatrixTranslate(float x, float y, float z)
|
||||
{
|
||||
InternalRenderManager.MatrixTranslate(x, y, z);
|
||||
}
|
||||
|
||||
void C4JRender::MatrixRotate(float angle, float x, float y, float z)
|
||||
{
|
||||
InternalRenderManager.MatrixRotate(angle, x, y, z);
|
||||
}
|
||||
|
||||
void C4JRender::MatrixScale(float x, float y, float z)
|
||||
{
|
||||
InternalRenderManager.MatrixScale(x, y, z);
|
||||
}
|
||||
|
||||
void C4JRender::MatrixPerspective(float fovy, float aspect, float zNear, float zFar)
|
||||
{
|
||||
InternalRenderManager.MatrixPerspective(fovy, aspect, zNear, zFar);
|
||||
}
|
||||
|
||||
void C4JRender::MatrixOrthogonal(float left, float right, float bottom, float top, float zNear, float zFar)
|
||||
{
|
||||
InternalRenderManager.MatrixOrthogonal(left, right, bottom, top, zNear, zFar);
|
||||
}
|
||||
|
||||
void C4JRender::MatrixPop()
|
||||
{
|
||||
InternalRenderManager.MatrixPop();
|
||||
}
|
||||
|
||||
void C4JRender::MatrixPush()
|
||||
{
|
||||
InternalRenderManager.MatrixPush();
|
||||
}
|
||||
|
||||
void C4JRender::MatrixMult(float* mat)
|
||||
{
|
||||
InternalRenderManager.MatrixMult(mat);
|
||||
}
|
||||
|
||||
const float* C4JRender::MatrixGet(int type)
|
||||
{
|
||||
return InternalRenderManager.MatrixGet(type);
|
||||
}
|
||||
|
||||
void C4JRender::Set_matrixDirty()
|
||||
{
|
||||
InternalRenderManager.Set_matrixDirty();
|
||||
}
|
||||
|
||||
void C4JRender::Initialise(ID3D11Device* pDevice, IDXGISwapChain* pSwapChain)
|
||||
{
|
||||
InternalRenderManager.Initialise(pDevice, pSwapChain);
|
||||
}
|
||||
|
||||
void C4JRender::InitialiseContext()
|
||||
{
|
||||
InternalRenderManager.InitialiseContext(false);
|
||||
}
|
||||
|
||||
void C4JRender::StartFrame()
|
||||
{
|
||||
InternalRenderManager.StartFrame();
|
||||
}
|
||||
|
||||
void C4JRender::DoScreenGrabOnNextPresent()
|
||||
{
|
||||
InternalRenderManager.DoScreenGrabOnNextPresent();
|
||||
}
|
||||
|
||||
void C4JRender::Present()
|
||||
{
|
||||
InternalRenderManager.Present();
|
||||
}
|
||||
|
||||
void C4JRender::Clear(int flags, D3D11_RECT* pRect)
|
||||
{
|
||||
InternalRenderManager.Clear(flags, pRect);
|
||||
}
|
||||
|
||||
void C4JRender::SetClearColour(const float colourRGBA[4])
|
||||
{
|
||||
InternalRenderManager.SetClearColour(colourRGBA);
|
||||
}
|
||||
|
||||
bool C4JRender::IsWidescreen()
|
||||
{
|
||||
return InternalRenderManager.IsWidescreen();
|
||||
}
|
||||
|
||||
bool C4JRender::IsHiDef()
|
||||
{
|
||||
return InternalRenderManager.IsHiDef();
|
||||
}
|
||||
|
||||
void C4JRender::CaptureThumbnail(ImageFileBuffer* pngOut)
|
||||
{
|
||||
InternalRenderManager.CaptureThumbnail(pngOut);
|
||||
}
|
||||
|
||||
void C4JRender::CaptureScreen(ImageFileBuffer* jpgOut, XSOCIAL_PREVIEWIMAGE* previewOut)
|
||||
{
|
||||
InternalRenderManager.CaptureScreen(jpgOut, previewOut);
|
||||
}
|
||||
|
||||
void C4JRender::BeginConditionalSurvey(int identifier)
|
||||
{
|
||||
InternalRenderManager.BeginConditionalSurvey(identifier);
|
||||
}
|
||||
|
||||
void C4JRender::EndConditionalSurvey()
|
||||
{
|
||||
InternalRenderManager.EndConditionalSurvey();
|
||||
}
|
||||
|
||||
void C4JRender::BeginConditionalRendering(int identifier)
|
||||
{
|
||||
InternalRenderManager.BeginConditionalRendering(identifier);
|
||||
}
|
||||
|
||||
void C4JRender::EndConditionalRendering()
|
||||
{
|
||||
InternalRenderManager.EndConditionalRendering();
|
||||
}
|
||||
|
||||
void C4JRender::DrawVertices(ePrimitiveType PrimitiveType, int count, void* dataIn, eVertexType vType, ePixelShaderType psType)
|
||||
{
|
||||
InternalRenderManager.DrawVertices(PrimitiveType, count, dataIn, vType, psType);
|
||||
}
|
||||
|
||||
void C4JRender::DrawVertexBuffer(ePrimitiveType PrimitiveType, int count, ID3D11Buffer* buffer, eVertexType vType, ePixelShaderType psType)
|
||||
{
|
||||
InternalRenderManager.DrawVertexBuffer(PrimitiveType, count, buffer, vType, psType);
|
||||
}
|
||||
|
||||
void C4JRender::CBuffLockStaticCreations()
|
||||
{
|
||||
InternalRenderManager.CBuffLockStaticCreations();
|
||||
}
|
||||
|
||||
int C4JRender::CBuffCreate(int count)
|
||||
{
|
||||
return InternalRenderManager.CBuffCreate(count);
|
||||
}
|
||||
|
||||
void C4JRender::CBuffDelete(int first, int count)
|
||||
{
|
||||
InternalRenderManager.CBuffDelete(first, count);
|
||||
}
|
||||
|
||||
void C4JRender::CBuffStart(int index, bool full)
|
||||
{
|
||||
InternalRenderManager.CBuffStart(index, full);
|
||||
}
|
||||
|
||||
void C4JRender::CBuffClear(int index)
|
||||
{
|
||||
InternalRenderManager.CBuffClear(index);
|
||||
}
|
||||
|
||||
int C4JRender::CBuffSize(int index)
|
||||
{
|
||||
return InternalRenderManager.CBuffSize(index);
|
||||
}
|
||||
|
||||
void C4JRender::CBuffEnd()
|
||||
{
|
||||
InternalRenderManager.CBuffEnd();
|
||||
}
|
||||
|
||||
bool C4JRender::CBuffCall(int index, bool full)
|
||||
{
|
||||
return InternalRenderManager.CBuffCall(index, full);
|
||||
}
|
||||
|
||||
void C4JRender::CBuffTick()
|
||||
{
|
||||
InternalRenderManager.CBuffTick();
|
||||
}
|
||||
|
||||
void C4JRender::CBuffDeferredModeStart()
|
||||
{
|
||||
InternalRenderManager.CBuffDeferredModeStart();
|
||||
}
|
||||
|
||||
void C4JRender::CBuffDeferredModeEnd()
|
||||
{
|
||||
InternalRenderManager.CBuffDeferredModeEnd();
|
||||
}
|
||||
|
||||
int C4JRender::TextureCreate()
|
||||
{
|
||||
return InternalRenderManager.TextureCreate();
|
||||
}
|
||||
|
||||
void C4JRender::TextureFree(int idx)
|
||||
{
|
||||
InternalRenderManager.TextureFree(idx);
|
||||
}
|
||||
|
||||
void C4JRender::TextureBind(int idx)
|
||||
{
|
||||
InternalRenderManager.TextureBind(idx);
|
||||
}
|
||||
|
||||
void C4JRender::TextureBindVertex(int idx)
|
||||
{
|
||||
InternalRenderManager.TextureBindVertex(idx);
|
||||
}
|
||||
|
||||
void C4JRender::TextureSetTextureLevels(int levels)
|
||||
{
|
||||
InternalRenderManager.TextureSetTextureLevels(levels);
|
||||
}
|
||||
|
||||
int C4JRender::TextureGetTextureLevels()
|
||||
{
|
||||
return InternalRenderManager.TextureGetTextureLevels();
|
||||
}
|
||||
|
||||
void C4JRender::TextureData(int width, int height, void* data, int level, eTextureFormat format)
|
||||
{
|
||||
InternalRenderManager.TextureData(width, height, data, level, format);
|
||||
}
|
||||
|
||||
void C4JRender::TextureDataUpdate(int xoffset, int yoffset, int width, int height, void* data, int level)
|
||||
{
|
||||
InternalRenderManager.TextureDataUpdate(xoffset, yoffset, width, height, data, level);
|
||||
}
|
||||
|
||||
void C4JRender::TextureSetParam(int param, int value)
|
||||
{
|
||||
InternalRenderManager.TextureSetParam(param, value);
|
||||
}
|
||||
|
||||
void C4JRender::TextureDynamicUpdateStart()
|
||||
{
|
||||
InternalRenderManager.TextureDynamicUpdateStart();
|
||||
}
|
||||
|
||||
void C4JRender::TextureDynamicUpdateEnd()
|
||||
{
|
||||
InternalRenderManager.TextureDynamicUpdateEnd();
|
||||
}
|
||||
|
||||
HRESULT C4JRender::LoadTextureData(const char* szFilename, D3DXIMAGE_INFO* pSrcInfo, int** ppDataOut)
|
||||
{
|
||||
return InternalRenderManager.LoadTextureData(szFilename, pSrcInfo, ppDataOut);
|
||||
}
|
||||
|
||||
HRESULT C4JRender::LoadTextureData(BYTE* pbData, DWORD dwBytes, D3DXIMAGE_INFO* pSrcInfo, int** ppDataOut)
|
||||
{
|
||||
return InternalRenderManager.LoadTextureData(pbData, dwBytes, pSrcInfo, ppDataOut);
|
||||
}
|
||||
|
||||
HRESULT C4JRender::SaveTextureData(const char* szFilename, D3DXIMAGE_INFO* pSrcInfo, int* ppDataOut)
|
||||
{
|
||||
return InternalRenderManager.SaveTextureData(szFilename, pSrcInfo, ppDataOut);
|
||||
}
|
||||
|
||||
HRESULT C4JRender::SaveTextureDataToMemory(void* pOutput, int outputCapacity, int* outputLength, int width, int height, int* ppDataIn)
|
||||
{
|
||||
return InternalRenderManager.SaveTextureDataToMemory(pOutput, outputCapacity, outputLength, width, height, ppDataIn);
|
||||
}
|
||||
|
||||
void C4JRender::TextureGetStats()
|
||||
{
|
||||
}
|
||||
|
||||
ID3D11ShaderResourceView* C4JRender::TextureGetTexture(int idx)
|
||||
{
|
||||
return InternalRenderManager.TextureGetTexture(idx);
|
||||
}
|
||||
|
||||
void C4JRender::StateSetColour(float r, float g, float b, float a)
|
||||
{
|
||||
InternalRenderManager.StateSetColour(r, g, b, a);
|
||||
}
|
||||
|
||||
void C4JRender::StateSetDepthMask(bool enable)
|
||||
{
|
||||
InternalRenderManager.StateSetDepthMask(enable);
|
||||
}
|
||||
|
||||
void C4JRender::StateSetBlendEnable(bool enable)
|
||||
{
|
||||
InternalRenderManager.StateSetBlendEnable(enable);
|
||||
}
|
||||
|
||||
void C4JRender::StateSetBlendFunc(int src, int dst)
|
||||
{
|
||||
InternalRenderManager.StateSetBlendFunc(src, dst);
|
||||
}
|
||||
|
||||
void C4JRender::StateSetBlendFactor(unsigned int colour)
|
||||
{
|
||||
InternalRenderManager.StateSetBlendFactor(colour);
|
||||
}
|
||||
|
||||
void C4JRender::StateSetAlphaFunc(int func, float param)
|
||||
{
|
||||
InternalRenderManager.StateSetAlphaFunc(func, param);
|
||||
}
|
||||
|
||||
void C4JRender::StateSetDepthFunc(int func)
|
||||
{
|
||||
InternalRenderManager.StateSetDepthFunc(func);
|
||||
}
|
||||
|
||||
void C4JRender::StateSetFaceCull(bool enable)
|
||||
{
|
||||
InternalRenderManager.StateSetFaceCull(enable);
|
||||
}
|
||||
|
||||
void C4JRender::StateSetFaceCullCW(bool enable)
|
||||
{
|
||||
InternalRenderManager.StateSetFaceCullCW(enable);
|
||||
}
|
||||
|
||||
void C4JRender::StateSetLineWidth(float width)
|
||||
{
|
||||
InternalRenderManager.StateSetLineWidth(width);
|
||||
}
|
||||
|
||||
void C4JRender::StateSetWriteEnable(bool red, bool green, bool blue, bool alpha)
|
||||
{
|
||||
InternalRenderManager.StateSetWriteEnable(red, green, blue, alpha);
|
||||
}
|
||||
|
||||
void C4JRender::StateSetDepthTestEnable(bool enable)
|
||||
{
|
||||
InternalRenderManager.StateSetDepthTestEnable(enable);
|
||||
}
|
||||
|
||||
void C4JRender::StateSetAlphaTestEnable(bool enable)
|
||||
{
|
||||
InternalRenderManager.StateSetAlphaTestEnable(enable);
|
||||
}
|
||||
|
||||
void C4JRender::StateSetDepthSlopeAndBias(float slope, float bias)
|
||||
{
|
||||
InternalRenderManager.StateSetDepthSlopeAndBias(slope, bias);
|
||||
}
|
||||
|
||||
void C4JRender::StateSetFogEnable(bool enable)
|
||||
{
|
||||
InternalRenderManager.StateSetFogEnable(enable);
|
||||
}
|
||||
|
||||
void C4JRender::StateSetFogMode(int mode)
|
||||
{
|
||||
InternalRenderManager.StateSetFogMode(mode);
|
||||
}
|
||||
|
||||
void C4JRender::StateSetFogNearDistance(float dist)
|
||||
{
|
||||
InternalRenderManager.StateSetFogNearDistance(dist);
|
||||
}
|
||||
|
||||
void C4JRender::StateSetFogFarDistance(float dist)
|
||||
{
|
||||
InternalRenderManager.StateSetFogFarDistance(dist);
|
||||
}
|
||||
|
||||
void C4JRender::StateSetFogDensity(float density)
|
||||
{
|
||||
InternalRenderManager.StateSetFogDensity(density);
|
||||
}
|
||||
|
||||
void C4JRender::StateSetFogColour(float red, float green, float blue)
|
||||
{
|
||||
InternalRenderManager.StateSetFogColour(red, green, blue);
|
||||
}
|
||||
|
||||
void C4JRender::StateSetLightingEnable(bool enable)
|
||||
{
|
||||
InternalRenderManager.StateSetLightingEnable(enable);
|
||||
}
|
||||
|
||||
void C4JRender::StateSetVertexTextureUV(float u, float v)
|
||||
{
|
||||
InternalRenderManager.StateSetVertexTextureUV(u, v);
|
||||
}
|
||||
|
||||
void C4JRender::StateSetLightColour(int light, float red, float green, float blue)
|
||||
{
|
||||
InternalRenderManager.StateSetLightColour(light, red, green, blue);
|
||||
}
|
||||
|
||||
void C4JRender::StateSetLightAmbientColour(float red, float green, float blue)
|
||||
{
|
||||
InternalRenderManager.StateSetLightAmbientColour(red, green, blue);
|
||||
}
|
||||
|
||||
void C4JRender::StateSetLightDirection(int light, float x, float y, float z)
|
||||
{
|
||||
InternalRenderManager.StateSetLightDirection(light, x, y, z);
|
||||
}
|
||||
|
||||
void C4JRender::StateSetLightEnable(int light, bool enable)
|
||||
{
|
||||
InternalRenderManager.StateSetLightEnable(light, enable);
|
||||
}
|
||||
|
||||
void C4JRender::StateSetViewport(eViewportType viewportType)
|
||||
{
|
||||
InternalRenderManager.StateSetViewport(viewportType);
|
||||
}
|
||||
|
||||
void C4JRender::StateSetEnableViewportClipPlanes(bool enable)
|
||||
{
|
||||
InternalRenderManager.StateSetEnableViewportClipPlanes(enable);
|
||||
}
|
||||
|
||||
void C4JRender::StateSetTexGenCol(int col, float x, float y, float z, float w, bool eyeSpace)
|
||||
{
|
||||
InternalRenderManager.StateSetTexGenCol(col, x, y, z, w, eyeSpace);
|
||||
}
|
||||
|
||||
void C4JRender::StateSetStencil(int Function, uint8_t stencil_ref, uint8_t stencil_func_mask, uint8_t stencil_write_mask)
|
||||
{
|
||||
InternalRenderManager.StateSetStencil((D3D11_COMPARISON_FUNC)Function, stencil_ref, stencil_func_mask, stencil_write_mask);
|
||||
}
|
||||
|
||||
void C4JRender::StateSetForceLOD(int LOD)
|
||||
{
|
||||
InternalRenderManager.StateSetForceLOD(LOD);
|
||||
}
|
||||
|
||||
void C4JRender::BeginEvent(LPCWSTR eventName)
|
||||
{
|
||||
InternalRenderManager.BeginEvent(eventName);
|
||||
}
|
||||
|
||||
void C4JRender::EndEvent()
|
||||
{
|
||||
InternalRenderManager.EndEvent();
|
||||
}
|
||||
|
||||
void C4JRender::Suspend()
|
||||
{
|
||||
InternalRenderManager.Suspend();
|
||||
}
|
||||
|
||||
bool C4JRender::Suspended()
|
||||
{
|
||||
return InternalRenderManager.Suspended();
|
||||
}
|
||||
|
||||
void C4JRender::Resume()
|
||||
{
|
||||
InternalRenderManager.Resume();
|
||||
}
|
||||
@@ -0,0 +1,844 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2026 Patoke
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "Renderer.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <new>
|
||||
|
||||
Renderer::CommandBuffer::CommandBuffer(bool full)
|
||||
: m_vertexBuffer(NULL)
|
||||
, m_vertexData(NULL)
|
||||
, m_vertexDataLength(0)
|
||||
, m_commands()
|
||||
, m_allocated(0x1000)
|
||||
, isActive(full ? 1 : 0)
|
||||
{
|
||||
m_vertexData = std::malloc(m_allocated);
|
||||
EnterCriticalSection(&Renderer::totalAllocCS);
|
||||
Renderer::totalAlloc += static_cast<int>(m_allocated);
|
||||
LeaveCriticalSection(&Renderer::totalAllocCS);
|
||||
}
|
||||
|
||||
Renderer::CommandBuffer::~CommandBuffer()
|
||||
{
|
||||
if (m_vertexBuffer)
|
||||
m_vertexBuffer->Release();
|
||||
|
||||
std::free(m_vertexData);
|
||||
|
||||
EnterCriticalSection(&Renderer::totalAllocCS);
|
||||
Renderer::totalAlloc -= static_cast<int>(m_allocated);
|
||||
LeaveCriticalSection(&Renderer::totalAllocCS);
|
||||
}
|
||||
|
||||
void Renderer::CommandBuffer::AddMatrix(const float *matrix)
|
||||
{
|
||||
Command command = {};
|
||||
command.m_command_type = COMMAND_ADD_MATRIX;
|
||||
std::memcpy(command.add_matrix.m_matrix, matrix, sizeof(command.add_matrix.m_matrix));
|
||||
m_commands.push_back(command);
|
||||
}
|
||||
|
||||
void Renderer::CommandBuffer::AddVertices(unsigned int stride, unsigned int count, void *dataIn, Renderer::Context &c)
|
||||
{
|
||||
PROFILER_SCOPE("Renderer::CommandBuffer::AddVertices", "AddVertices", MP_ORANGE);
|
||||
|
||||
if (c.matrixDirty[MATRIX_MODE_MODELVIEW_CBUFF])
|
||||
{
|
||||
AddMatrix(InternalRenderManager.MatrixGet(MATRIX_MODE_MODELVIEW_CBUFF));
|
||||
c.matrixDirty[MATRIX_MODE_MODELVIEW_CBUFF] = false;
|
||||
}
|
||||
|
||||
const std::uint64_t vertexOffset = m_vertexDataLength;
|
||||
const std::uint64_t copySize = std::uint64_t(stride) * std::uint64_t(count);
|
||||
|
||||
Command command = {};
|
||||
command.m_command_type = COMMAND_ADD_VERTICES;
|
||||
command.add_vertices.m_vertex_index_start = static_cast<unsigned int>(vertexOffset);
|
||||
command.add_vertices.m_vertex_count = count;
|
||||
|
||||
m_vertexDataLength = vertexOffset + copySize;
|
||||
if (m_vertexDataLength > m_allocated)
|
||||
{
|
||||
EnterCriticalSection(&Renderer::totalAllocCS);
|
||||
Renderer::totalAlloc -= static_cast<int>(m_allocated);
|
||||
LeaveCriticalSection(&Renderer::totalAllocCS);
|
||||
|
||||
m_allocated = ((m_vertexDataLength + (0x1000 - 1)) & ~(0x1000 - 1));
|
||||
m_vertexData = std::realloc(m_vertexData, m_allocated);
|
||||
|
||||
EnterCriticalSection(&Renderer::totalAllocCS);
|
||||
Renderer::totalAlloc += static_cast<int>(m_allocated);
|
||||
LeaveCriticalSection(&Renderer::totalAllocCS);
|
||||
}
|
||||
|
||||
const std::size_t byteCount = std::size_t(stride) * std::size_t(count);
|
||||
std::memcpy(static_cast<std::uint8_t*>(m_vertexData) + vertexOffset, dataIn, byteCount);
|
||||
m_commands.push_back(command);
|
||||
}
|
||||
|
||||
void Renderer::CommandBuffer::BindTexture(int idx)
|
||||
{
|
||||
Command command = {};
|
||||
command.m_command_type = COMMAND_BIND_TEXTURE;
|
||||
command.bind_texture.m_texture_index = idx;
|
||||
m_commands.push_back(command);
|
||||
}
|
||||
|
||||
bool Renderer::CBuffCall(int index, bool full)
|
||||
{
|
||||
EnterCriticalSection(&m_commandBufferCS);
|
||||
|
||||
bool result = false;
|
||||
const int commandIndex = m_vertexIdxToBufferIdx[index];
|
||||
if (commandIndex >= 0)
|
||||
{
|
||||
Renderer::Context &c = getContext();
|
||||
const std::uint8_t vertexType = m_commandVertexTypes[commandIndex];
|
||||
const std::uint8_t primitiveType = m_commandPrimitiveTypes[commandIndex];
|
||||
|
||||
if (full)
|
||||
{
|
||||
if (c.matrixDirty[MATRIX_MODE_MODELVIEW])
|
||||
{
|
||||
D3D11_MAPPED_SUBRESOURCE mappedMatrix0 = {};
|
||||
c.m_pDeviceContext->Map(c.m_modelViewMatrix, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedMatrix0);
|
||||
std::memcpy(mappedMatrix0.pData, MatrixGet(MATRIX_MODE_MODELVIEW), sizeof(DirectX::XMMATRIX));
|
||||
c.m_pDeviceContext->Unmap(c.m_modelViewMatrix, 0);
|
||||
c.matrixDirty[MATRIX_MODE_MODELVIEW] = false;
|
||||
}
|
||||
|
||||
if (c.matrixDirty[MATRIX_MODE_MODELVIEW_PROJECTION])
|
||||
{
|
||||
D3D11_MAPPED_SUBRESOURCE mappedMatrix2 = {};
|
||||
c.m_pDeviceContext->Map(c.m_projectionMatrix, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedMatrix2);
|
||||
std::memcpy(mappedMatrix2.pData, MatrixGet(MATRIX_MODE_MODELVIEW_PROJECTION), sizeof(DirectX::XMMATRIX));
|
||||
c.m_pDeviceContext->Unmap(c.m_projectionMatrix, 0);
|
||||
c.matrixDirty[MATRIX_MODE_MODELVIEW_PROJECTION] = false;
|
||||
}
|
||||
|
||||
if (c.matrixDirty[MATRIX_MODE_MODELVIEW_TEXTURE])
|
||||
{
|
||||
D3D11_MAPPED_SUBRESOURCE mappedMatrix3 = {};
|
||||
c.m_pDeviceContext->Map(c.m_textureMatrix, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedMatrix3);
|
||||
std::memcpy(mappedMatrix3.pData, MatrixGet(MATRIX_MODE_MODELVIEW_TEXTURE), sizeof(DirectX::XMMATRIX));
|
||||
c.m_pDeviceContext->Unmap(c.m_textureMatrix, 0);
|
||||
c.matrixDirty[MATRIX_MODE_MODELVIEW_TEXTURE] = false;
|
||||
}
|
||||
|
||||
UpdateFogState();
|
||||
UpdateLightingState();
|
||||
UpdateViewportState();
|
||||
UpdateTexGenState();
|
||||
|
||||
if (vertexType != activeVertexType)
|
||||
{
|
||||
c.m_pDeviceContext->VSSetShader(vertexShaderTable[vertexType], NULL, 0);
|
||||
c.m_pDeviceContext->IASetInputLayout(inputLayoutTable[vertexType]);
|
||||
activeVertexType = vertexType;
|
||||
}
|
||||
|
||||
int pixelType = 0;
|
||||
if (static_cast<int>(c.forcedLOD) > -1)
|
||||
{
|
||||
const float forcedLod[4] = {static_cast<float>(static_cast<int>(c.forcedLOD)), 0.0f, 0.0f, 0.0f};
|
||||
D3D11_MAPPED_SUBRESOURCE mappedAux4 = {};
|
||||
c.m_pDeviceContext->Map(c.m_forcedLODBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedAux4);
|
||||
std::memcpy(mappedAux4.pData, forcedLod, sizeof(forcedLod));
|
||||
c.m_pDeviceContext->Unmap(c.m_forcedLODBuffer, 0);
|
||||
pixelType = C4JRender::PIXEL_SHADER_TYPE_FORCELOD;
|
||||
}
|
||||
|
||||
if (static_cast<DWORD>(pixelType) != activePixelType)
|
||||
{
|
||||
c.m_pDeviceContext->PSSetShader(pixelShaderTable[pixelType], NULL, 0);
|
||||
activePixelType = pixelType;
|
||||
}
|
||||
|
||||
c.m_pDeviceContext->IASetPrimitiveTopology(g_topologies[primitiveType]);
|
||||
|
||||
ID3D11Buffer *indexBuffer = NULL;
|
||||
if (primitiveType == C4JRender::PRIMITIVE_TYPE_QUAD_LIST)
|
||||
indexBuffer = quadIndexBuffer;
|
||||
else if (primitiveType == C4JRender::PRIMITIVE_TYPE_TRIANGLE_FAN)
|
||||
indexBuffer = fanIndexBuffer;
|
||||
|
||||
c.m_pDeviceContext->IASetIndexBuffer(indexBuffer, DXGI_FORMAT_R16_UINT, 0);
|
||||
}
|
||||
|
||||
m_commandBuffers[commandIndex]->Render(static_cast<C4JRender::eVertexType>(vertexType), c, primitiveType);
|
||||
|
||||
if (full)
|
||||
{
|
||||
MultWithStack(m_commandMatrices[commandIndex]);
|
||||
c.matrixStacks[MATRIX_MODE_MODELVIEW_CBUFF][0] = DirectX::XMMatrixIdentity();
|
||||
c.matrixDirty[MATRIX_MODE_MODELVIEW_CBUFF] = true;
|
||||
}
|
||||
|
||||
result = true;
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&m_commandBufferCS);
|
||||
return result;
|
||||
}
|
||||
|
||||
void Renderer::CBuffClear(int index)
|
||||
{
|
||||
EnterCriticalSection(&m_commandBufferCS);
|
||||
|
||||
const int internalIndex = m_vertexIdxToBufferIdx[index];
|
||||
if (internalIndex >= 0)
|
||||
{
|
||||
DeleteInternalBuffer(internalIndex);
|
||||
m_vertexIdxToBufferIdx[index] = static_cast<std::int16_t>(-2);
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&m_commandBufferCS);
|
||||
}
|
||||
|
||||
int Renderer::CBuffCreate(int count)
|
||||
{
|
||||
EnterCriticalSection(&m_commandBufferCS);
|
||||
|
||||
int first = reservedRendererDword1;
|
||||
if (first < NUM_COMMAND_HANDLES)
|
||||
{
|
||||
int probe = first;
|
||||
int end = first + count;
|
||||
while (true)
|
||||
{
|
||||
assert(first < NUM_COMMAND_HANDLES);
|
||||
|
||||
int cursor = probe;
|
||||
while (cursor < end && cursor < NUM_COMMAND_HANDLES && m_vertexIdxToBufferIdx[cursor] == static_cast<std::int16_t>(-1))
|
||||
{
|
||||
++cursor;
|
||||
}
|
||||
|
||||
if (cursor >= end)
|
||||
break;
|
||||
|
||||
++first;
|
||||
++probe;
|
||||
++end;
|
||||
if (first >= NUM_COMMAND_HANDLES || end > NUM_COMMAND_HANDLES)
|
||||
{
|
||||
first = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (first >= 0)
|
||||
{
|
||||
const int allocationEnd = first + count;
|
||||
for (int i = first; i < allocationEnd; ++i)
|
||||
m_vertexIdxToBufferIdx[i] = static_cast<std::int16_t>(-2);
|
||||
|
||||
if (reservedRendererByte1)
|
||||
reservedRendererDword1 = allocationEnd;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
first = -1;
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&m_commandBufferCS);
|
||||
return first;
|
||||
}
|
||||
|
||||
void Renderer::CBuffDeferredModeEnd()
|
||||
{
|
||||
Renderer::Context &c = getContext();
|
||||
if (!c.deferredModeEnabled)
|
||||
return;
|
||||
|
||||
EnterCriticalSection(&m_commandBufferCS);
|
||||
c.deferredModeEnabled = false;
|
||||
|
||||
for (std::vector<Renderer::DeferredCBuff>::const_iterator it = c.deferredBuffers.begin(); it != c.deferredBuffers.end(); ++it)
|
||||
{
|
||||
const Renderer::DeferredCBuff &deferred = *it;
|
||||
const int existingIndex = m_vertexIdxToBufferIdx[deferred.m_vertex_index];
|
||||
if (existingIndex >= 0)
|
||||
DeleteInternalBuffer(existingIndex);
|
||||
|
||||
if (static_cast<int>(m_currentCommandBuffer + m_numBuffersToDeallocate + 10) > MAX_COMMAND_BUFFERS)
|
||||
DebugBreak();
|
||||
|
||||
const int internalSlot = m_currentCommandBuffer;
|
||||
++m_currentCommandBuffer;
|
||||
|
||||
m_vertexIdxToBufferIdx[deferred.m_vertex_index] = static_cast<std::int16_t>(internalSlot);
|
||||
m_bufferIdxToVertexIdx[internalSlot] = deferred.m_vertex_index;
|
||||
m_commandVertexTypes[internalSlot] = static_cast<std::uint8_t>(deferred.m_vertex_type);
|
||||
m_commandPrimitiveTypes[internalSlot] = static_cast<std::uint8_t>(deferred.m_primitive_type);
|
||||
m_commandBuffers[internalSlot] = deferred.m_command_buf;
|
||||
m_commandMatrices[internalSlot] = deferred.m_matrix;
|
||||
}
|
||||
|
||||
c.deferredBuffers.clear();
|
||||
LeaveCriticalSection(&m_commandBufferCS);
|
||||
}
|
||||
|
||||
void Renderer::CBuffDeferredModeStart()
|
||||
{
|
||||
getContext().deferredModeEnabled = true;
|
||||
}
|
||||
|
||||
void Renderer::CBuffDelete(int first, int count)
|
||||
{
|
||||
EnterCriticalSection(&m_commandBufferCS);
|
||||
|
||||
const int end = first + count;
|
||||
for (int i = first; i < end; ++i)
|
||||
{
|
||||
const int internalIndex = m_vertexIdxToBufferIdx[i];
|
||||
if (internalIndex >= 0)
|
||||
DeleteInternalBuffer(internalIndex);
|
||||
|
||||
m_vertexIdxToBufferIdx[i] = static_cast<std::int16_t>(-1);
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&m_commandBufferCS);
|
||||
}
|
||||
|
||||
void Renderer::CBuffEnd()
|
||||
{
|
||||
Renderer::Context &c = getContext();
|
||||
|
||||
assert(c.stackType == MATRIX_MODE_MODELVIEW_CBUFF);
|
||||
assert(c.stackPos[MATRIX_MODE_MODELVIEW_CBUFF] == 0);
|
||||
|
||||
EnterCriticalSection(&m_commandBufferCS);
|
||||
|
||||
if (c.deferredModeEnabled)
|
||||
{
|
||||
Renderer::DeferredCBuff deferred;
|
||||
deferred.m_command_buf = c.commandBuffer;
|
||||
deferred.m_vertex_index = c.recordingBufferIndex;
|
||||
deferred.m_vertex_type = c.recordingVertexType;
|
||||
deferred.m_primitive_type = c.recordingPrimitiveType;
|
||||
deferred.m_matrix = c.matrixStacks[MATRIX_MODE_MODELVIEW_CBUFF][0];
|
||||
c.deferredBuffers.push_back(deferred);
|
||||
}
|
||||
else
|
||||
{
|
||||
const int existingIndex = m_vertexIdxToBufferIdx[c.recordingBufferIndex];
|
||||
if (existingIndex >= 0)
|
||||
DeleteInternalBuffer(existingIndex);
|
||||
|
||||
if (static_cast<int>(m_currentCommandBuffer + m_numBuffersToDeallocate + 10) > MAX_COMMAND_BUFFERS)
|
||||
DebugBreak();
|
||||
|
||||
const int internalSlot = m_currentCommandBuffer;
|
||||
++m_currentCommandBuffer;
|
||||
|
||||
m_vertexIdxToBufferIdx[c.recordingBufferIndex] = static_cast<std::int16_t>(internalSlot);
|
||||
m_bufferIdxToVertexIdx[internalSlot] = c.recordingBufferIndex;
|
||||
m_commandVertexTypes[internalSlot] = static_cast<std::uint8_t>(c.recordingVertexType);
|
||||
m_commandPrimitiveTypes[internalSlot] = static_cast<std::uint8_t>(c.recordingPrimitiveType);
|
||||
m_commandBuffers[internalSlot] = c.commandBuffer;
|
||||
m_commandMatrices[internalSlot] = c.matrixStacks[MATRIX_MODE_MODELVIEW_CBUFF][0];
|
||||
}
|
||||
|
||||
c.stackType = MATRIX_MODE_MODELVIEW;
|
||||
c.commandBuffer->EndRecording(m_pDevice);
|
||||
c.commandBuffer = NULL;
|
||||
|
||||
LeaveCriticalSection(&m_commandBufferCS);
|
||||
}
|
||||
|
||||
void Renderer::CBuffLockStaticCreations()
|
||||
{
|
||||
reservedRendererByte1 = 0;
|
||||
}
|
||||
|
||||
int Renderer::CBuffSize(int index)
|
||||
{
|
||||
if (index == -1)
|
||||
return totalAlloc < 0 ? 0 : totalAlloc;
|
||||
|
||||
unsigned int size = 0;
|
||||
EnterCriticalSection(&m_commandBufferCS);
|
||||
const int commandIndex = m_vertexIdxToBufferIdx[index];
|
||||
if (commandIndex >= 0)
|
||||
size = static_cast<unsigned int>(m_commandBuffers[commandIndex]->GetAllocated());
|
||||
LeaveCriticalSection(&m_commandBufferCS);
|
||||
return size;
|
||||
}
|
||||
|
||||
void Renderer::CBuffStart(int index, bool full)
|
||||
{
|
||||
Renderer::Context &c = getContext();
|
||||
c.commandBuffer = new (std::nothrow) Renderer::CommandBuffer(full);
|
||||
c.recordingBufferIndex = index;
|
||||
|
||||
assert(c.stackType == MATRIX_MODE_MODELVIEW);
|
||||
|
||||
c.stackType = MATRIX_MODE_MODELVIEW_CBUFF;
|
||||
c.stackPos[MATRIX_MODE_MODELVIEW_CBUFF] = 0;
|
||||
c.matrixStacks[MATRIX_MODE_MODELVIEW_CBUFF][0] = DirectX::XMMatrixIdentity();
|
||||
c.matrixDirty[MATRIX_MODE_MODELVIEW_CBUFF] = true;
|
||||
}
|
||||
|
||||
void Renderer::CBuffTick()
|
||||
{
|
||||
EnterCriticalSection(&m_commandBufferCS);
|
||||
|
||||
int completedDeletes = 0;
|
||||
if (m_numBuffersToDeallocate > 0)
|
||||
{
|
||||
int deleteIdx = MAX_COMMAND_BUFFERS - 1;
|
||||
do
|
||||
{
|
||||
Renderer::CommandBuffer *buffer = m_commandBuffers[deleteIdx];
|
||||
if (buffer)
|
||||
delete buffer;
|
||||
m_commandBuffers[deleteIdx] = NULL;
|
||||
|
||||
if (--m_numBuffersToDeallocate == 0)
|
||||
{
|
||||
++completedDeletes;
|
||||
--deleteIdx;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_commandBuffers[deleteIdx] = m_commandBuffers[(MAX_COMMAND_BUFFERS - 1) - static_cast<int>(m_numBuffersToDeallocate)];
|
||||
}
|
||||
} while (completedDeletes < static_cast<int>(m_numBuffersToDeallocate));
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&m_commandBufferCS);
|
||||
}
|
||||
|
||||
void Renderer::DeleteInternalBuffer(int index)
|
||||
{
|
||||
EnterCriticalSection(&m_commandBufferCS);
|
||||
|
||||
++m_numBuffersToDeallocate;
|
||||
const int index_delete = MAX_COMMAND_BUFFERS - static_cast<int>(m_numBuffersToDeallocate);
|
||||
|
||||
m_commandBuffers[index_delete] = m_commandBuffers[index];
|
||||
m_commandMatrices[index_delete] = m_commandMatrices[index];
|
||||
|
||||
if (m_currentCommandBuffer-- != 1)
|
||||
{
|
||||
const int mappedFrom = m_currentCommandBuffer;
|
||||
|
||||
m_commandBuffers[index] = m_commandBuffers[mappedFrom];
|
||||
m_commandMatrices[index] = m_commandMatrices[mappedFrom];
|
||||
m_commandVertexTypes[index] = m_commandVertexTypes[mappedFrom];
|
||||
m_commandPrimitiveTypes[index] = m_commandPrimitiveTypes[mappedFrom];
|
||||
|
||||
const int commandIndex = m_bufferIdxToVertexIdx[mappedFrom];
|
||||
m_vertexIdxToBufferIdx[commandIndex] = static_cast<std::int16_t>(index);
|
||||
m_bufferIdxToVertexIdx[index] = commandIndex;
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&m_commandBufferCS);
|
||||
}
|
||||
|
||||
void Renderer::CommandBuffer::EndRecording(ID3D11Device *device)
|
||||
{
|
||||
if (m_vertexDataLength != 0)
|
||||
{
|
||||
D3D11_BUFFER_DESC desc = {};
|
||||
desc.ByteWidth = static_cast<UINT>(m_vertexDataLength);
|
||||
desc.Usage = D3D11_USAGE_IMMUTABLE;
|
||||
desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
|
||||
|
||||
D3D11_SUBRESOURCE_DATA data = {};
|
||||
data.pSysMem = m_vertexData;
|
||||
device->CreateBuffer(&desc, &data, &m_vertexBuffer);
|
||||
}
|
||||
|
||||
std::free(m_vertexData);
|
||||
m_vertexData = NULL;
|
||||
}
|
||||
|
||||
std::uint64_t Renderer::CommandBuffer::GetAllocated()
|
||||
{
|
||||
return m_allocated;
|
||||
}
|
||||
|
||||
bool Renderer::CommandBuffer::IsBusy()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void Renderer::CommandBuffer::Render(C4JRender::eVertexType vType, Renderer::Context &c, int primitiveType)
|
||||
{
|
||||
PROFILER_SCOPE("Renderer::CommandBuffer::Render", "Render", MP_ORANGE);
|
||||
|
||||
if (!m_vertexBuffer)
|
||||
return;
|
||||
|
||||
int drawVertexType = vType;
|
||||
int shaderVertexType = drawVertexType;
|
||||
bool matrixOverride = false;
|
||||
|
||||
for (const Command &command : m_commands)
|
||||
{
|
||||
PROFILER_SCOPE("Renderer::CommandBuffer::Render", "ProcessCommand", MP_ORANGE);
|
||||
|
||||
switch (command.m_command_type)
|
||||
{
|
||||
case COMMAND_ADD_MATRIX:
|
||||
{
|
||||
if (drawVertexType == C4JRender::VERTEX_TYPE_COMPRESSED)
|
||||
{
|
||||
const float row[4] = {
|
||||
command.add_matrix.m_matrix[12], command.add_matrix.m_matrix[13],
|
||||
command.add_matrix.m_matrix[14], command.add_matrix.m_matrix[15]
|
||||
};
|
||||
D3D11_MAPPED_SUBRESOURCE mappedAux0 = {};
|
||||
c.m_pDeviceContext->Map(c.m_compressedTranslationBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedAux0);
|
||||
std::memcpy(mappedAux0.pData, row, sizeof(row));
|
||||
c.m_pDeviceContext->Unmap(c.m_compressedTranslationBuffer, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
D3D11_MAPPED_SUBRESOURCE mappedMatrix1 = {};
|
||||
c.m_pDeviceContext->Map(c.m_localTransformMatrix, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedMatrix1);
|
||||
std::memcpy(mappedMatrix1.pData, command.add_matrix.m_matrix, sizeof(command.add_matrix.m_matrix));
|
||||
c.m_pDeviceContext->Unmap(c.m_localTransformMatrix, 0);
|
||||
matrixOverride = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case COMMAND_ADD_VERTICES:
|
||||
{
|
||||
if (isActive)
|
||||
{
|
||||
InternalRenderManager.UpdateLightingState();
|
||||
|
||||
if (drawVertexType == C4JRender::VERTEX_TYPE_PF3_TF2_CB4_NB4_XW1)
|
||||
{
|
||||
if (c.lightingEnabled)
|
||||
{
|
||||
drawVertexType = C4JRender::VERTEX_TYPE_PF3_TF2_CB4_NB4_XW1_LIT;
|
||||
shaderVertexType = C4JRender::VERTEX_TYPE_PF3_TF2_CB4_NB4_XW1_LIT;
|
||||
}
|
||||
}
|
||||
else if (drawVertexType == C4JRender::VERTEX_TYPE_PF3_TF2_CB4_NB4_XW1_LIT && !c.lightingEnabled)
|
||||
{
|
||||
drawVertexType = C4JRender::VERTEX_TYPE_PF3_TF2_CB4_NB4_XW1;
|
||||
shaderVertexType = C4JRender::VERTEX_TYPE_PF3_TF2_CB4_NB4_XW1;
|
||||
}
|
||||
|
||||
if (static_cast<DWORD>(drawVertexType) != InternalRenderManager.activeVertexType)
|
||||
{
|
||||
c.m_pDeviceContext->VSSetShader(InternalRenderManager.vertexShaderTable[shaderVertexType], NULL, 0);
|
||||
c.m_pDeviceContext->IASetInputLayout(InternalRenderManager.inputLayoutTable[shaderVertexType]);
|
||||
InternalRenderManager.activeVertexType = drawVertexType;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int drawCount = command.add_vertices.m_vertex_count;
|
||||
bool drawIndexed = false;
|
||||
if (primitiveType == C4JRender::PRIMITIVE_TYPE_QUAD_LIST)
|
||||
{
|
||||
drawCount = (drawCount * 6) / 4;
|
||||
drawIndexed = true;
|
||||
}
|
||||
else if (primitiveType == C4JRender::PRIMITIVE_TYPE_TRIANGLE_FAN)
|
||||
{
|
||||
drawCount = (drawCount - 2) * 3;
|
||||
drawIndexed = true;
|
||||
}
|
||||
|
||||
ID3D11Buffer *buffer = m_vertexBuffer;
|
||||
const UINT stride = InternalRenderManager.vertexStrideTable[drawVertexType];
|
||||
const UINT offset = command.add_vertices.m_vertex_index_start;
|
||||
c.m_pDeviceContext->IASetVertexBuffers(0, 1, &buffer, &stride, &offset);
|
||||
|
||||
if (drawIndexed)
|
||||
c.m_pDeviceContext->DrawIndexed(drawCount, 0, 0);
|
||||
else
|
||||
c.m_pDeviceContext->Draw(drawCount, 0);
|
||||
break;
|
||||
}
|
||||
case COMMAND_BIND_TEXTURE:
|
||||
{
|
||||
c.textureIdx = command.bind_texture.m_texture_index;
|
||||
ID3D11ShaderResourceView *view = InternalRenderManager.m_textures[c.textureIdx].view;
|
||||
c.m_pDeviceContext->PSSetShaderResources(0, 1, &view);
|
||||
InternalRenderManager.UpdateTextureState(false);
|
||||
break;
|
||||
}
|
||||
case COMMAND_SET_COLOR:
|
||||
{
|
||||
D3D11_MAPPED_SUBRESOURCE mappedColour = {};
|
||||
c.m_pDeviceContext->Map(c.m_tintColorBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedColour);
|
||||
std::memcpy(mappedColour.pData, command.set_color.m_color, sizeof(command.set_color.m_color));
|
||||
c.m_pDeviceContext->Unmap(c.m_tintColorBuffer, 0);
|
||||
break;
|
||||
}
|
||||
case COMMAND_SET_DEPTH_FUNC:
|
||||
{
|
||||
c.depthStencilDesc.DepthFunc = static_cast<D3D11_COMPARISON_FUNC>(command.set_depth_func.m_depth_func);
|
||||
c.m_pDeviceContext->OMSetDepthStencilState(InternalRenderManager.GetManagedDepthStencilState(), 0);
|
||||
break;
|
||||
}
|
||||
case COMMAND_SET_DEPTH_MASK:
|
||||
{
|
||||
c.depthWriteEnabled = command.set_depth_mask.m_enable;
|
||||
c.depthStencilDesc.DepthWriteMask = command.set_depth_mask.m_enable ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
|
||||
c.m_pDeviceContext->OMSetDepthStencilState(InternalRenderManager.GetManagedDepthStencilState(), 0);
|
||||
break;
|
||||
}
|
||||
case COMMAND_SET_DEPTH_TEST:
|
||||
{
|
||||
c.depthTestEnabled = command.set_depth_test.m_enable;
|
||||
c.depthStencilDesc.DepthEnable = command.set_depth_test.m_enable;
|
||||
c.m_pDeviceContext->OMSetDepthStencilState(InternalRenderManager.GetManagedDepthStencilState(), 0);
|
||||
break;
|
||||
}
|
||||
case COMMAND_SET_LIGHTING_ENABLE:
|
||||
{
|
||||
c.lightingEnabled = command.set_lighting_enable.m_enable;
|
||||
break;
|
||||
}
|
||||
case COMMAND_SET_LIGHT_ENABLE:
|
||||
{
|
||||
const int light = command.set_light_enable.m_light_index;
|
||||
if (light >= 0 && light < 2)
|
||||
{
|
||||
c.lightEnabled[light] = command.set_light_enable.m_enable;
|
||||
c.lightingDirty = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case COMMAND_SET_LIGHT_DIRECTION:
|
||||
{
|
||||
const int light = command.set_light_direction.m_light_index;
|
||||
if (light >= 0 && light < 2)
|
||||
{
|
||||
c.lightDirection[light].x = command.set_light_direction.m_direction[0];
|
||||
c.lightDirection[light].y = command.set_light_direction.m_direction[1];
|
||||
c.lightDirection[light].z = command.set_light_direction.m_direction[2];
|
||||
c.lightDirection[light].w = command.set_light_direction.m_direction[3];
|
||||
c.lightingDirty = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case COMMAND_SET_LIGHT_COLOUR:
|
||||
{
|
||||
const int light = command.set_light_colour.m_light_index;
|
||||
if (light >= 0 && light < 2)
|
||||
{
|
||||
c.lightColour[light].x = command.set_light_colour.m_color[0];
|
||||
c.lightColour[light].y = command.set_light_colour.m_color[1];
|
||||
c.lightColour[light].z = command.set_light_colour.m_color[2];
|
||||
c.lightColour[light].w = 1.0f;
|
||||
c.lightingDirty = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case COMMAND_SET_LIGHT_AMBIENT_COLOUR:
|
||||
{
|
||||
c.lightAmbientColour.x = command.set_light_ambient_colour.m_color[0];
|
||||
c.lightAmbientColour.y = command.set_light_ambient_colour.m_color[1];
|
||||
c.lightAmbientColour.z = command.set_light_ambient_colour.m_color[2];
|
||||
c.lightAmbientColour.w = 1.0f;
|
||||
c.lightingDirty = true;
|
||||
break;
|
||||
}
|
||||
case COMMAND_SET_BLEND_ENABLE:
|
||||
{
|
||||
c.blendDesc.RenderTarget[0].BlendEnable = command.set_blend_enable.m_enable;
|
||||
break;
|
||||
}
|
||||
case COMMAND_SET_BLEND_FUNC:
|
||||
{
|
||||
c.blendDesc.RenderTarget[0].SrcBlend = static_cast<D3D11_BLEND>(command.set_blend_func.m_src);
|
||||
c.blendDesc.RenderTarget[0].DestBlend = static_cast<D3D11_BLEND>(command.set_blend_func.m_dst);
|
||||
c.m_pDeviceContext->OMSetBlendState(InternalRenderManager.GetManagedBlendState(), c.blendFactor, 0xFFFFFFFF);
|
||||
break;
|
||||
}
|
||||
case COMMAND_SET_BLEND_FACTOR:
|
||||
{
|
||||
const unsigned int factor = command.set_blend_factor.m_blend_factor;
|
||||
c.blendFactor[0] = float((factor >> 0) & 0xFF) / 255.0f;
|
||||
c.blendFactor[1] = float((factor >> 8) & 0xFF) / 255.0f;
|
||||
c.blendFactor[2] = float((factor >> 16) & 0xFF) / 255.0f;
|
||||
c.blendFactor[3] = float((factor >> 24) & 0xFF) / 255.0f;
|
||||
c.m_pDeviceContext->OMSetBlendState(InternalRenderManager.GetManagedBlendState(), c.blendFactor, 0xFFFFFFFF);
|
||||
break;
|
||||
}
|
||||
case COMMAND_SET_FACE_CULL:
|
||||
{
|
||||
c.rasterizerDesc.CullMode = command.set_face_cull.m_enable ? D3D11_CULL_BACK : D3D11_CULL_NONE;
|
||||
c.m_pDeviceContext->RSSetState(InternalRenderManager.GetManagedRasterizerState());
|
||||
c.faceCullEnabled = command.set_face_cull.m_enable;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (matrixOverride)
|
||||
{
|
||||
const DirectX::XMMATRIX identity = DirectX::XMMatrixIdentity();
|
||||
D3D11_MAPPED_SUBRESOURCE mappedIdentity = {};
|
||||
c.m_pDeviceContext->Map(c.m_localTransformMatrix, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedIdentity);
|
||||
std::memcpy(mappedIdentity.pData, &identity, sizeof(identity));
|
||||
c.m_pDeviceContext->Unmap(c.m_localTransformMatrix, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::CommandBuffer::SetBlendEnable(bool enable)
|
||||
{
|
||||
Command command = {};
|
||||
command.m_command_type = COMMAND_SET_BLEND_ENABLE;
|
||||
command.set_blend_enable.m_enable = enable;
|
||||
m_commands.push_back(command);
|
||||
}
|
||||
|
||||
void Renderer::CommandBuffer::SetBlendFactor(unsigned int factor)
|
||||
{
|
||||
Command command = {};
|
||||
command.m_command_type = COMMAND_SET_BLEND_FACTOR;
|
||||
command.set_blend_factor.m_blend_factor = factor;
|
||||
m_commands.push_back(command);
|
||||
}
|
||||
|
||||
void Renderer::CommandBuffer::SetBlendFunc(int src, int dst)
|
||||
{
|
||||
Command command = {};
|
||||
command.m_command_type = COMMAND_SET_BLEND_FUNC;
|
||||
command.set_blend_func.m_src = src;
|
||||
command.set_blend_func.m_dst = dst;
|
||||
m_commands.push_back(command);
|
||||
}
|
||||
|
||||
void Renderer::CommandBuffer::SetColor(float r, float g, float b, float a)
|
||||
{
|
||||
Command command = {};
|
||||
command.m_command_type = COMMAND_SET_COLOR;
|
||||
command.set_color.m_color[0] = r;
|
||||
command.set_color.m_color[1] = g;
|
||||
command.set_color.m_color[2] = b;
|
||||
command.set_color.m_color[3] = a;
|
||||
m_commands.push_back(command);
|
||||
}
|
||||
|
||||
void Renderer::CommandBuffer::SetDepthFunc(int func)
|
||||
{
|
||||
Command command = {};
|
||||
command.m_command_type = COMMAND_SET_DEPTH_FUNC;
|
||||
command.set_depth_func.m_depth_func = func;
|
||||
m_commands.push_back(command);
|
||||
}
|
||||
|
||||
void Renderer::CommandBuffer::SetDepthMask(bool enable)
|
||||
{
|
||||
Command command = {};
|
||||
command.m_command_type = COMMAND_SET_DEPTH_MASK;
|
||||
command.set_depth_mask.m_enable = enable;
|
||||
m_commands.push_back(command);
|
||||
}
|
||||
|
||||
void Renderer::CommandBuffer::SetDepthTestEnable(bool enable)
|
||||
{
|
||||
Command command = {};
|
||||
command.m_command_type = COMMAND_SET_DEPTH_TEST;
|
||||
command.set_depth_test.m_enable = enable;
|
||||
m_commands.push_back(command);
|
||||
}
|
||||
|
||||
void Renderer::CommandBuffer::SetFaceCull(bool enable)
|
||||
{
|
||||
Command command = {};
|
||||
command.m_command_type = COMMAND_SET_FACE_CULL;
|
||||
command.set_face_cull.m_enable = enable;
|
||||
m_commands.push_back(command);
|
||||
}
|
||||
|
||||
void Renderer::CommandBuffer::SetLightAmbientColour(float r, float g, float b)
|
||||
{
|
||||
Command command = {};
|
||||
command.m_command_type = COMMAND_SET_LIGHT_AMBIENT_COLOUR;
|
||||
command.set_light_ambient_colour.m_color[0] = r;
|
||||
command.set_light_ambient_colour.m_color[1] = g;
|
||||
command.set_light_ambient_colour.m_color[2] = b;
|
||||
m_commands.push_back(command);
|
||||
}
|
||||
|
||||
void Renderer::CommandBuffer::SetLightColour(int light, float r, float g, float b)
|
||||
{
|
||||
Command command = {};
|
||||
command.m_command_type = COMMAND_SET_LIGHT_COLOUR;
|
||||
command.set_light_colour.m_light_index = light;
|
||||
command.set_light_colour.m_color[0] = r;
|
||||
command.set_light_colour.m_color[1] = g;
|
||||
command.set_light_colour.m_color[2] = b;
|
||||
m_commands.push_back(command);
|
||||
}
|
||||
|
||||
void Renderer::CommandBuffer::SetLightDirection(int light, float x, float y, float z)
|
||||
{
|
||||
Renderer::Context &c = InternalRenderManager.getContext();
|
||||
const std::uint32_t depth = c.stackPos[MATRIX_MODE_MODELVIEW_CBUFF];
|
||||
const DirectX::XMMATRIX &matrix = c.matrixStacks[MATRIX_MODE_MODELVIEW_CBUFF][depth];
|
||||
|
||||
DirectX::XMVECTOR direction = DirectX::XMVectorSet(x, y, z, 0.0f);
|
||||
direction = DirectX::XMVector3TransformNormal(direction, matrix);
|
||||
direction = DirectX::XMVector3Normalize(direction);
|
||||
|
||||
Command command = {};
|
||||
command.m_command_type = COMMAND_SET_LIGHT_DIRECTION;
|
||||
command.set_light_direction.m_light_index = light;
|
||||
DirectX::XMFLOAT4 outDirection;
|
||||
DirectX::XMStoreFloat4(&outDirection, direction);
|
||||
command.set_light_direction.m_direction[0] = outDirection.x;
|
||||
command.set_light_direction.m_direction[1] = outDirection.y;
|
||||
command.set_light_direction.m_direction[2] = outDirection.z;
|
||||
command.set_light_direction.m_direction[3] = outDirection.w;
|
||||
m_commands.push_back(command);
|
||||
}
|
||||
|
||||
void Renderer::CommandBuffer::SetLightEnable(int light, bool enable)
|
||||
{
|
||||
Command command = {};
|
||||
command.m_command_type = COMMAND_SET_LIGHT_ENABLE;
|
||||
command.set_light_enable.m_light_index = light;
|
||||
command.set_light_enable.m_enable = enable;
|
||||
m_commands.push_back(command);
|
||||
}
|
||||
|
||||
void Renderer::CommandBuffer::SetLightingEnable(bool enable)
|
||||
{
|
||||
Command command = {};
|
||||
command.m_command_type = COMMAND_SET_LIGHTING_ENABLE;
|
||||
command.set_lighting_enable.m_enable = enable;
|
||||
m_commands.push_back(command);
|
||||
}
|
||||
|
||||
void Renderer::CommandBuffer::StartRecording() {}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2026 Patoke
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "Renderer.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
const float *Renderer::MatrixGet(int type)
|
||||
{
|
||||
Context &c = getContext();
|
||||
const int depth = c.stackPos[type];
|
||||
const DirectX::XMMATRIX &matrix = c.matrixStacks[type][depth];
|
||||
return &matrix.r[0].m128_f32[0];
|
||||
}
|
||||
|
||||
void Renderer::MatrixMode(int type)
|
||||
{
|
||||
Context &c = getContext();
|
||||
assert(type >= 0);
|
||||
assert(type < STACK_TYPES);
|
||||
c.stackType = type;
|
||||
}
|
||||
|
||||
void Renderer::MatrixMult(float *mat)
|
||||
{
|
||||
DirectX::XMMATRIX matrix;
|
||||
std::memcpy(&matrix, mat, sizeof(matrix));
|
||||
MultWithStack(matrix);
|
||||
}
|
||||
|
||||
void Renderer::MatrixOrthogonal(float left, float right, float bottom, float top, float zNear, float zFar)
|
||||
{
|
||||
const DirectX::XMMATRIX matrix = DirectX::XMMatrixOrthographicOffCenterRH(left, right, bottom, top, zNear, zFar);
|
||||
MultWithStack(matrix);
|
||||
}
|
||||
|
||||
void Renderer::MatrixPerspective(float fovy, float aspect, float zNear, float zFar)
|
||||
{
|
||||
const float fovRadians = fovy * (PI / 180.0f);
|
||||
const DirectX::XMMATRIX matrix = DirectX::XMMatrixPerspectiveFovRH(fovRadians, aspect, zNear, zFar);
|
||||
MultWithStack(matrix);
|
||||
}
|
||||
|
||||
void Renderer::MatrixPop()
|
||||
{
|
||||
Context &c = getContext();
|
||||
|
||||
assert(c.stackPos[c.stackType] > 0);
|
||||
|
||||
const int mode = c.stackType;
|
||||
--c.stackPos[mode];
|
||||
c.matrixDirty[mode] = true;
|
||||
}
|
||||
|
||||
void Renderer::MatrixPush()
|
||||
{
|
||||
Context &c = getContext();
|
||||
|
||||
assert(c.stackPos[c.stackType] < (STACK_SIZE - 1));
|
||||
|
||||
const int mode = c.stackType;
|
||||
const int depth = c.stackPos[mode];
|
||||
c.matrixStacks[mode][depth + 1] = c.matrixStacks[mode][depth];
|
||||
++c.stackPos[mode];
|
||||
}
|
||||
|
||||
void Renderer::MatrixRotate(float angle, float x, float y, float z)
|
||||
{
|
||||
const DirectX::XMVECTOR axis = DirectX::XMVectorSet(x, y, z, 0.0f);
|
||||
const DirectX::XMMATRIX matrix = DirectX::XMMatrixRotationAxis(axis, angle);
|
||||
MultWithStack(matrix);
|
||||
}
|
||||
|
||||
void Renderer::MatrixScale(float x, float y, float z)
|
||||
{
|
||||
const DirectX::XMMATRIX matrix = DirectX::XMMatrixScaling(x, y, z);
|
||||
MultWithStack(matrix);
|
||||
}
|
||||
|
||||
void Renderer::MatrixSetIdentity()
|
||||
{
|
||||
Context &c = getContext();
|
||||
const int mode = c.stackType;
|
||||
const int depth = c.stackPos[mode];
|
||||
c.matrixStacks[mode][depth] = DirectX::XMMatrixIdentity();
|
||||
c.matrixDirty[mode] = true;
|
||||
}
|
||||
|
||||
void Renderer::MatrixTranslate(float x, float y, float z)
|
||||
{
|
||||
const DirectX::XMMATRIX matrix = DirectX::XMMatrixTranslation(x, y, z);
|
||||
MultWithStack(matrix);
|
||||
}
|
||||
|
||||
void Renderer::MultWithStack(DirectX::XMMATRIX matrix)
|
||||
{
|
||||
Context &c = getContext();
|
||||
const int mode = c.stackType;
|
||||
const int depth = c.stackPos[mode];
|
||||
DirectX::XMMATRIX ¤t = c.matrixStacks[mode][depth];
|
||||
current = DirectX::XMMatrixMultiply(matrix, current);
|
||||
c.matrixDirty[mode] = true;
|
||||
}
|
||||
|
||||
void Renderer::Set_matrixDirty()
|
||||
{
|
||||
Context &c = getContext();
|
||||
const DirectX::XMMATRIX identity = DirectX::XMMatrixIdentity();
|
||||
|
||||
c.matrixStacks[MATRIX_MODE_MODELVIEW][0] = identity;
|
||||
c.matrixStacks[MATRIX_MODE_MODELVIEW_PROJECTION][0] = identity;
|
||||
c.matrixStacks[MATRIX_MODE_MODELVIEW_TEXTURE][0] = identity;
|
||||
c.matrixStacks[MATRIX_MODE_MODELVIEW_CBUFF][0] = identity;
|
||||
|
||||
c.matrixDirty[MATRIX_MODE_MODELVIEW] = true;
|
||||
c.matrixDirty[MATRIX_MODE_MODELVIEW_PROJECTION] = true;
|
||||
c.matrixDirty[MATRIX_MODE_MODELVIEW_TEXTURE] = true;
|
||||
c.matrixDirty[MATRIX_MODE_MODELVIEW_CBUFF] = true;
|
||||
|
||||
activeVertexType = -1;
|
||||
activePixelType = -1;
|
||||
}
|
||||
@@ -0,0 +1,688 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2026 Patoke
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "Renderer.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
|
||||
|
||||
ID3D11BlendState *Renderer::GetManagedBlendState()
|
||||
{
|
||||
PROFILER_SCOPE("Renderer::GetManagedBlendState", "GetManagedBlendState", MP_ORCHID1);
|
||||
Context &c = getContext();
|
||||
const D3D11_RENDER_TARGET_BLEND_DESC &rtBlend = c.blendDesc.RenderTarget[0];
|
||||
|
||||
const int key = (rtBlend.BlendEnable ? 1 : 0) | ((static_cast<int>(rtBlend.SrcBlend) & 0x1F) << 1) |
|
||||
((static_cast<int>(rtBlend.DestBlend) & 0x1F) << 6) | ((static_cast<int>(rtBlend.RenderTargetWriteMask) & 0x0F) << 11);
|
||||
|
||||
auto it = managedBlendStates.find(key);
|
||||
if (it != managedBlendStates.end())
|
||||
return it->second;
|
||||
|
||||
ID3D11BlendState *state = NULL;
|
||||
m_pDevice->CreateBlendState(&c.blendDesc, &state);
|
||||
managedBlendStates.emplace(key, state);
|
||||
return state;
|
||||
}
|
||||
|
||||
|
||||
ID3D11DepthStencilState *Renderer::GetManagedDepthStencilState()
|
||||
{
|
||||
PROFILER_SCOPE("Renderer::GetManagedBlendState", "GetManagedDepthStencilState", MP_ORCHID1);
|
||||
Context &c = getContext();
|
||||
|
||||
const int key = (c.depthStencilDesc.DepthEnable ? 2 : 0) | ((static_cast<int>(c.depthStencilDesc.DepthFunc) & 0x0F) << 2) |
|
||||
(c.depthStencilDesc.DepthWriteMask == D3D11_DEPTH_WRITE_MASK_ALL ? 1 : 0);
|
||||
|
||||
auto it = managedDepthStencilStates.find(key);
|
||||
if (it != managedDepthStencilStates.end())
|
||||
return it->second;
|
||||
|
||||
ID3D11DepthStencilState *state = NULL;
|
||||
m_pDevice->CreateDepthStencilState(&c.depthStencilDesc, &state);
|
||||
managedDepthStencilStates.emplace(key, state);
|
||||
return state;
|
||||
}
|
||||
|
||||
|
||||
ID3D11RasterizerState *Renderer::GetManagedRasterizerState()
|
||||
{
|
||||
PROFILER_SCOPE("Renderer::GetManagedRasterizerState", "GetManagedRasterizerState", MP_ORCHID1);
|
||||
Context &c = getContext();
|
||||
|
||||
const int key = (static_cast<std::uint8_t>(c.rasterizerDesc.DepthBias)) |
|
||||
(static_cast<std::uint8_t>(static_cast<int>(c.rasterizerDesc.SlopeScaledDepthBias)) << 8) |
|
||||
((static_cast<int>(c.rasterizerDesc.CullMode) & 0x03) << 16);
|
||||
|
||||
auto it = managedRasterizerStates.find(key);
|
||||
if (it != managedRasterizerStates.end())
|
||||
return it->second;
|
||||
|
||||
ID3D11RasterizerState *state = NULL;
|
||||
m_pDevice->CreateRasterizerState(&c.rasterizerDesc, &state);
|
||||
managedRasterizerStates.emplace(key, state);
|
||||
return state;
|
||||
}
|
||||
|
||||
|
||||
ID3D11SamplerState *Renderer::GetManagedSamplerState()
|
||||
{
|
||||
PROFILER_SCOPE("Renderer::GetManagedSamplerState", "GetManagedSamplerState", MP_ORCHID1);
|
||||
Context &c = getContext();
|
||||
const int key = m_textures[c.textureIdx].samplerParams;
|
||||
|
||||
auto it = managedSamplerStates.find(key);
|
||||
if (it != managedSamplerStates.end())
|
||||
return it->second;
|
||||
|
||||
const bool clampU = (key & SAMPLER_PARAM_CLAMP_U) != 0;
|
||||
const bool clampV = (key & SAMPLER_PARAM_CLAMP_V) != 0;
|
||||
const bool linearFilter = (key & SAMPLER_PARAM_LINEAR_FILTER) != 0;
|
||||
const bool mipLinear = (key & SAMPLER_PARAM_LINEAR_MIPS) != 0;
|
||||
const int filterBits = (mipLinear != 0 ? (linearFilter ? D3D11_FILTER_MIN_MAG_MIP_LINEAR : D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR)
|
||||
: (linearFilter ? D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR : D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR));
|
||||
|
||||
D3D11_SAMPLER_DESC desc = {};
|
||||
desc.Filter = static_cast<D3D11_FILTER>(filterBits);
|
||||
desc.AddressU = clampU ? D3D11_TEXTURE_ADDRESS_CLAMP : D3D11_TEXTURE_ADDRESS_WRAP;
|
||||
desc.AddressV = clampV ? D3D11_TEXTURE_ADDRESS_CLAMP : D3D11_TEXTURE_ADDRESS_WRAP;
|
||||
desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
|
||||
desc.MipLODBias = 0.0f;
|
||||
desc.MaxAnisotropy = 16;
|
||||
desc.ComparisonFunc = D3D11_COMPARISON_NEVER;
|
||||
desc.BorderColor[0] = 0.0f;
|
||||
desc.BorderColor[1] = 0.0f;
|
||||
desc.BorderColor[2] = 0.0f;
|
||||
desc.BorderColor[3] = 0.0f;
|
||||
desc.MinLOD = -(std::numeric_limits<float>::max)();
|
||||
desc.MaxLOD = (std::numeric_limits<float>::max)();
|
||||
|
||||
ID3D11SamplerState *state = NULL;
|
||||
m_pDevice->CreateSamplerState(&desc, &state);
|
||||
managedSamplerStates.emplace(key, state);
|
||||
return state;
|
||||
}
|
||||
|
||||
|
||||
void Renderer::StateSetAlphaFunc(int, float param)
|
||||
{
|
||||
Context &c = getContext();
|
||||
c.alphaReference = param;
|
||||
|
||||
const float alpha[4] = {0.0f, 0.0f, 0.0f, c.alphaTestEnabled ? c.alphaReference : 0.0f};
|
||||
D3D11_MAPPED_SUBRESOURCE mapped = {};
|
||||
c.m_pDeviceContext->Map(c.m_alphaTestBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
|
||||
std::memcpy(mapped.pData, alpha, sizeof(alpha));
|
||||
c.m_pDeviceContext->Unmap(c.m_alphaTestBuffer, 0);
|
||||
}
|
||||
|
||||
|
||||
void Renderer::StateSetAlphaTestEnable(bool enable)
|
||||
{
|
||||
Context &c = getContext();
|
||||
c.alphaTestEnabled = enable;
|
||||
|
||||
const float alpha[4] = {0.0f, 0.0f, 0.0f, enable ? c.alphaReference : 0.0f};
|
||||
D3D11_MAPPED_SUBRESOURCE mapped = {};
|
||||
c.m_pDeviceContext->Map(c.m_alphaTestBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
|
||||
std::memcpy(mapped.pData, alpha, sizeof(alpha));
|
||||
c.m_pDeviceContext->Unmap(c.m_alphaTestBuffer, 0);
|
||||
}
|
||||
|
||||
|
||||
void Renderer::StateSetBlendEnable(bool enable)
|
||||
{
|
||||
Context &c = getContext();
|
||||
if (c.commandBuffer != NULL && c.commandBuffer->isActive != 0)
|
||||
{
|
||||
c.commandBuffer->SetBlendEnable(enable);
|
||||
return;
|
||||
}
|
||||
|
||||
c.blendDesc.RenderTarget[0].BlendEnable = enable;
|
||||
c.m_pDeviceContext->OMSetBlendState(GetManagedBlendState(), c.blendFactor, 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
|
||||
void Renderer::StateSetBlendFactor(unsigned int colour)
|
||||
{
|
||||
Context &c = getContext();
|
||||
if (c.commandBuffer != NULL && c.commandBuffer->isActive != 0)
|
||||
{
|
||||
c.commandBuffer->SetBlendFactor(colour);
|
||||
return;
|
||||
}
|
||||
|
||||
const float scale = 255.0f;
|
||||
c.blendFactor[0] = static_cast<float>((colour >> 0) & 0xFF) / scale;
|
||||
c.blendFactor[1] = static_cast<float>((colour >> 8) & 0xFF) / scale;
|
||||
c.blendFactor[2] = static_cast<float>((colour >> 16) & 0xFF) / scale;
|
||||
c.blendFactor[3] = static_cast<float>((colour >> 24) & 0xFF) / scale;
|
||||
c.m_pDeviceContext->OMSetBlendState(GetManagedBlendState(), c.blendFactor, 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
|
||||
void Renderer::StateSetBlendFunc(int src, int dst)
|
||||
{
|
||||
Context &c = getContext();
|
||||
if (c.commandBuffer != NULL && c.commandBuffer->isActive != 0)
|
||||
{
|
||||
c.commandBuffer->SetBlendFunc(src, dst);
|
||||
return;
|
||||
}
|
||||
|
||||
c.blendDesc.RenderTarget[0].SrcBlend = static_cast<D3D11_BLEND>(src);
|
||||
c.blendDesc.RenderTarget[0].DestBlend = static_cast<D3D11_BLEND>(dst);
|
||||
c.m_pDeviceContext->OMSetBlendState(GetManagedBlendState(), c.blendFactor, 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
|
||||
void Renderer::StateSetColour(float r, float g, float b, float a)
|
||||
{
|
||||
Context &c = getContext();
|
||||
if (c.commandBuffer != NULL && c.commandBuffer->isActive != 0)
|
||||
{
|
||||
c.commandBuffer->SetColor(r, g, b, a);
|
||||
return;
|
||||
}
|
||||
|
||||
ID3D11DeviceContext *d3d11 = c.m_pDeviceContext;
|
||||
const float colour[4] = {r, g, b, a};
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE mapped = {};
|
||||
d3d11->Map(c.m_tintColorBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
|
||||
std::memcpy(mapped.pData, colour, sizeof(colour));
|
||||
d3d11->Unmap(c.m_tintColorBuffer, 0);
|
||||
}
|
||||
|
||||
|
||||
void Renderer::StateSetDepthFunc(int func)
|
||||
{
|
||||
Context &c = getContext();
|
||||
if (c.commandBuffer != NULL && c.commandBuffer->isActive != 0)
|
||||
{
|
||||
c.commandBuffer->SetDepthFunc(func);
|
||||
return;
|
||||
}
|
||||
|
||||
c.depthStencilDesc.DepthFunc = static_cast<D3D11_COMPARISON_FUNC>(func);
|
||||
c.m_pDeviceContext->OMSetDepthStencilState(GetManagedDepthStencilState(), 0);
|
||||
}
|
||||
|
||||
|
||||
void Renderer::StateSetDepthMask(bool enable)
|
||||
{
|
||||
Context &c = getContext();
|
||||
if (c.commandBuffer != NULL && c.commandBuffer->isActive != 0)
|
||||
{
|
||||
c.commandBuffer->SetDepthMask(enable);
|
||||
return;
|
||||
}
|
||||
|
||||
c.depthStencilDesc.DepthWriteMask = enable ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
|
||||
c.m_pDeviceContext->OMSetDepthStencilState(GetManagedDepthStencilState(), 0);
|
||||
c.depthWriteEnabled = enable;
|
||||
}
|
||||
|
||||
|
||||
void Renderer::StateSetDepthSlopeAndBias(float slope, float bias)
|
||||
{
|
||||
Context &c = getContext();
|
||||
|
||||
const float scale = 65536.0f;
|
||||
c.rasterizerDesc.DepthBias = static_cast<int>(bias * scale);
|
||||
c.rasterizerDesc.SlopeScaledDepthBias = slope * scale;
|
||||
c.m_pDeviceContext->RSSetState(GetManagedRasterizerState());
|
||||
}
|
||||
|
||||
|
||||
void Renderer::StateSetDepthTestEnable(bool enable)
|
||||
{
|
||||
Context &c = getContext();
|
||||
if (c.commandBuffer != NULL && c.commandBuffer->isActive != 0)
|
||||
{
|
||||
c.commandBuffer->SetDepthTestEnable(enable);
|
||||
return;
|
||||
}
|
||||
|
||||
c.depthStencilDesc.DepthEnable = enable;
|
||||
c.m_pDeviceContext->OMSetDepthStencilState(GetManagedDepthStencilState(), 0);
|
||||
c.depthTestEnabled = enable;
|
||||
}
|
||||
|
||||
|
||||
void Renderer::StateSetEnableViewportClipPlanes(bool) {}
|
||||
|
||||
|
||||
void Renderer::StateSetFaceCull(bool enable)
|
||||
{
|
||||
Context &c = getContext();
|
||||
if (c.commandBuffer != NULL && c.commandBuffer->isActive != 0)
|
||||
{
|
||||
c.commandBuffer->SetFaceCull(enable);
|
||||
return;
|
||||
}
|
||||
|
||||
c.rasterizerDesc.CullMode = enable ? D3D11_CULL_BACK : D3D11_CULL_NONE;
|
||||
c.m_pDeviceContext->RSSetState(GetManagedRasterizerState());
|
||||
c.faceCullEnabled = enable;
|
||||
}
|
||||
|
||||
|
||||
void Renderer::StateSetFaceCullCW(bool enable)
|
||||
{
|
||||
Context &c = getContext();
|
||||
if (c.faceCullEnabled)
|
||||
c.rasterizerDesc.CullMode = enable ? D3D11_CULL_BACK : D3D11_CULL_FRONT;
|
||||
else
|
||||
c.rasterizerDesc.CullMode = D3D11_CULL_NONE;
|
||||
|
||||
c.m_pDeviceContext->RSSetState(GetManagedRasterizerState());
|
||||
}
|
||||
|
||||
|
||||
void Renderer::StateSetFogColour(float red, float green, float blue)
|
||||
{
|
||||
Context &c = getContext();
|
||||
c.fogColourRed = red;
|
||||
c.fogColourBlue = blue;
|
||||
c.fogColourGreen = green;
|
||||
}
|
||||
|
||||
|
||||
void Renderer::StateSetFogDensity(float density)
|
||||
{
|
||||
Context &c = getContext();
|
||||
c.fogDensity = density;
|
||||
}
|
||||
|
||||
|
||||
void Renderer::StateSetFogEnable(bool enable)
|
||||
{
|
||||
Context &c = getContext();
|
||||
c.fogEnabled = enable;
|
||||
}
|
||||
|
||||
|
||||
void Renderer::StateSetFogFarDistance(float dist)
|
||||
{
|
||||
Context &c = getContext();
|
||||
c.fogFarDistance = dist;
|
||||
}
|
||||
|
||||
|
||||
void Renderer::StateSetFogMode(int mode)
|
||||
{
|
||||
Context &c = getContext();
|
||||
c.fogMode = mode;
|
||||
}
|
||||
|
||||
|
||||
void Renderer::StateSetFogNearDistance(float dist)
|
||||
{
|
||||
Context &c = getContext();
|
||||
c.fogNearDistance = dist;
|
||||
}
|
||||
|
||||
|
||||
void Renderer::StateSetForceLOD(int LOD)
|
||||
{
|
||||
Context &c = getContext();
|
||||
c.forcedLOD = LOD;
|
||||
}
|
||||
|
||||
|
||||
void Renderer::StateSetLightAmbientColour(float red, float green, float blue)
|
||||
{
|
||||
Context &c = getContext();
|
||||
if (c.commandBuffer != NULL && c.commandBuffer->isActive != 0)
|
||||
{
|
||||
c.commandBuffer->SetLightAmbientColour(red, green, blue);
|
||||
return;
|
||||
}
|
||||
|
||||
c.lightAmbientColour.x = red;
|
||||
c.lightAmbientColour.y = green;
|
||||
c.lightAmbientColour.z = blue;
|
||||
c.lightAmbientColour.w = 1.0f;
|
||||
c.lightingDirty = true;
|
||||
}
|
||||
|
||||
|
||||
void Renderer::StateSetLightColour(int light, float red, float green, float blue)
|
||||
{
|
||||
if (light >= 2)
|
||||
return;
|
||||
|
||||
Context &c = getContext();
|
||||
if (c.commandBuffer != NULL && c.commandBuffer->isActive != 0)
|
||||
{
|
||||
c.commandBuffer->SetLightColour(light, red, green, blue);
|
||||
return;
|
||||
}
|
||||
|
||||
c.lightColour[light].x = red;
|
||||
c.lightColour[light].y = green;
|
||||
c.lightColour[light].z = blue;
|
||||
c.lightColour[light].w = 1.0f;
|
||||
c.lightingDirty = true;
|
||||
}
|
||||
|
||||
|
||||
void Renderer::StateSetLightDirection(int light, float x, float y, float z)
|
||||
{
|
||||
if (light >= 2)
|
||||
return;
|
||||
|
||||
Context &c = getContext();
|
||||
if (c.commandBuffer != NULL && c.commandBuffer->isActive != 0)
|
||||
{
|
||||
c.commandBuffer->SetLightDirection(light, x, y, z);
|
||||
return;
|
||||
}
|
||||
|
||||
const std::uint32_t stackIndex = c.stackPos[MATRIX_MODE_MODELVIEW];
|
||||
const DirectX::XMMATRIX &modelView = c.matrixStacks[MATRIX_MODE_MODELVIEW][stackIndex];
|
||||
const DirectX::XMVECTOR direction = DirectX::XMVectorSet(x, y, z, 0.0f);
|
||||
const DirectX::XMVECTOR transformed = DirectX::XMVector3TransformNormal(direction, modelView);
|
||||
const DirectX::XMVECTOR normalized = DirectX::XMVector3Normalize(transformed);
|
||||
|
||||
DirectX::XMStoreFloat4(&c.lightDirection[light], normalized);
|
||||
c.lightingDirty = true;
|
||||
}
|
||||
|
||||
|
||||
void Renderer::StateSetLightEnable(int light, bool enable)
|
||||
{
|
||||
if (light >= 2)
|
||||
return;
|
||||
|
||||
Context &c = getContext();
|
||||
if (c.commandBuffer != NULL && c.commandBuffer->isActive != 0)
|
||||
{
|
||||
c.commandBuffer->SetLightEnable(light, enable);
|
||||
return;
|
||||
}
|
||||
|
||||
c.lightEnabled[light] = enable;
|
||||
c.lightingDirty = true;
|
||||
}
|
||||
|
||||
|
||||
void Renderer::StateSetLightingEnable(bool enable)
|
||||
{
|
||||
Context &c = getContext();
|
||||
if (c.commandBuffer != NULL && c.commandBuffer->isActive != 0)
|
||||
{
|
||||
c.commandBuffer->SetLightingEnable(enable);
|
||||
return;
|
||||
}
|
||||
|
||||
c.lightingEnabled = enable;
|
||||
}
|
||||
|
||||
|
||||
void Renderer::StateSetLineWidth(float) {}
|
||||
|
||||
|
||||
void Renderer::StateSetStencil(D3D11_COMPARISON_FUNC function, uint8_t stencil_ref, uint8_t stencil_func_mask, uint8_t stencil_write_mask)
|
||||
{
|
||||
Context &c = getContext();
|
||||
|
||||
D3D11_DEPTH_STENCIL_DESC desc = c.depthStencilDesc;
|
||||
desc.StencilEnable = true;
|
||||
desc.StencilReadMask = stencil_func_mask;
|
||||
desc.StencilWriteMask = stencil_write_mask;
|
||||
desc.FrontFace.StencilFunc = function;
|
||||
desc.BackFace.StencilFunc = function;
|
||||
|
||||
ID3D11DepthStencilState *state = NULL;
|
||||
m_pDevice->CreateDepthStencilState(&desc, &state);
|
||||
m_pDeviceContext->OMSetDepthStencilState(state, stencil_ref);
|
||||
if (state != NULL) state->Release();
|
||||
}
|
||||
|
||||
|
||||
void Renderer::StateSetTexGenCol(int col, float x, float y, float z, float w, bool eyeSpace)
|
||||
{
|
||||
Context &c = getContext();
|
||||
|
||||
DirectX::XMVECTOR plane = DirectX::XMVectorSet(x, y, z, w);
|
||||
if (eyeSpace)
|
||||
{
|
||||
DirectX::XMFLOAT4X4 modelView;
|
||||
std::memset(&modelView, 0, sizeof(modelView));
|
||||
std::memcpy(&modelView, MatrixGet(MATRIX_MODE_MODELVIEW), sizeof(modelView));
|
||||
|
||||
DirectX::XMVECTOR determinant = DirectX::XMVectorZero();
|
||||
const DirectX::XMMATRIX inverse = DirectX::XMMatrixInverse(&determinant, DirectX::XMLoadFloat4x4(&modelView));
|
||||
plane = DirectX::XMVector4Transform(plane, inverse);
|
||||
}
|
||||
|
||||
DirectX::XMFLOAT4 transformed;
|
||||
DirectX::XMStoreFloat4(&transformed, plane);
|
||||
|
||||
const int activeSet = eyeSpace ? 0 : 1;
|
||||
const int inactiveSet = eyeSpace ? 1 : 0;
|
||||
|
||||
float *active = reinterpret_cast<float *>(&c.texGenMatrices[activeSet]);
|
||||
active[col + 0] = transformed.x;
|
||||
active[col + 4] = transformed.y;
|
||||
active[col + 8] = transformed.z;
|
||||
active[col + 12] = transformed.w;
|
||||
|
||||
float *inactive = reinterpret_cast<float *>(&c.texGenMatrices[inactiveSet]);
|
||||
inactive[col + 0] = 0.0f;
|
||||
inactive[col + 4] = 0.0f;
|
||||
inactive[col + 8] = 0.0f;
|
||||
inactive[col + 12] = 0.0f;
|
||||
}
|
||||
|
||||
|
||||
void Renderer::StateSetVertexTextureUV(float u, float v)
|
||||
{
|
||||
Context &c = getContext();
|
||||
const float texgen[4] = {u - 1.0f, v - 1.0f, 0.0f, 0.0f};
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE mapped = {};
|
||||
c.m_pDeviceContext->Map(c.m_vertexTexcoordBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
|
||||
std::memcpy(mapped.pData, texgen, sizeof(texgen));
|
||||
c.m_pDeviceContext->Unmap(c.m_vertexTexcoordBuffer, 0);
|
||||
}
|
||||
|
||||
|
||||
void Renderer::StateSetViewport(C4JRender::eViewportType viewportType)
|
||||
{
|
||||
getContext();
|
||||
m_ViewportType = viewportType;
|
||||
|
||||
const float fullWidth = static_cast<float>(backBufferWidth);
|
||||
const float fullHeight = static_cast<float>(backBufferHeight);
|
||||
|
||||
float x = 0.0f;
|
||||
float y = 0.0f;
|
||||
float width = fullWidth;
|
||||
float height = fullHeight;
|
||||
|
||||
switch (viewportType)
|
||||
{
|
||||
case C4JRender::VIEWPORT_TYPE_FULLSCREEN:
|
||||
break;
|
||||
case C4JRender::VIEWPORT_TYPE_SPLIT_TOP:
|
||||
height = fullHeight * 0.5f;
|
||||
break;
|
||||
case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM:
|
||||
y = fullHeight * 0.5f;
|
||||
height = fullHeight * 0.5f;
|
||||
break;
|
||||
case C4JRender::VIEWPORT_TYPE_SPLIT_LEFT:
|
||||
width = fullWidth * 0.5f;
|
||||
break;
|
||||
case C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT:
|
||||
x = fullWidth * 0.5f;
|
||||
width = fullWidth * 0.5f;
|
||||
break;
|
||||
case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_LEFT:
|
||||
width = fullWidth * 0.5f;
|
||||
height = fullHeight * 0.5f;
|
||||
break;
|
||||
case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_RIGHT:
|
||||
x = fullWidth * 0.5f;
|
||||
width = fullWidth * 0.5f;
|
||||
height = fullHeight * 0.5f;
|
||||
break;
|
||||
case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_LEFT:
|
||||
y = fullHeight * 0.5f;
|
||||
width = fullWidth * 0.5f;
|
||||
height = fullHeight * 0.5f;
|
||||
break;
|
||||
case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT:
|
||||
x = fullWidth * 0.5f;
|
||||
y = fullHeight * 0.5f;
|
||||
width = fullWidth * 0.5f;
|
||||
height = fullHeight * 0.5f;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
D3D11_VIEWPORT viewport = {};
|
||||
viewport.TopLeftX = x;
|
||||
viewport.TopLeftY = y;
|
||||
viewport.Width = width;
|
||||
viewport.Height = height;
|
||||
viewport.MinDepth = 0.0f;
|
||||
viewport.MaxDepth = 1.0f;
|
||||
|
||||
m_pDeviceContext->RSSetViewports(1, &viewport);
|
||||
m_pDeviceContext->OMSetRenderTargets(1, &mainRenderTargetView, depthStencilView);
|
||||
}
|
||||
|
||||
|
||||
void Renderer::StateSetWriteEnable(bool red, bool green, bool blue, bool alpha)
|
||||
{
|
||||
Context &c = getContext();
|
||||
|
||||
std::uint8_t mask = 0;
|
||||
mask |= red ? 0x1 : 0;
|
||||
mask |= green ? 0x2 : 0;
|
||||
mask |= blue ? 0x4 : 0;
|
||||
mask |= alpha ? 0x8 : 0;
|
||||
|
||||
c.blendDesc.RenderTarget[0].RenderTargetWriteMask = mask;
|
||||
c.m_pDeviceContext->OMSetBlendState(GetManagedBlendState(), c.blendFactor, 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
|
||||
void Renderer::StateUpdate()
|
||||
{
|
||||
PROFILER_SCOPE("Renderer::StateUpdate", "StateUpdate", MP_ORCHID1);
|
||||
Context &c = getContext();
|
||||
StateSetFaceCull(c.faceCullEnabled);
|
||||
StateSetDepthMask(c.depthWriteEnabled);
|
||||
StateSetDepthTestEnable(c.depthTestEnabled);
|
||||
StateSetAlphaTestEnable(c.alphaTestEnabled);
|
||||
}
|
||||
|
||||
void Renderer::UpdateFogState()
|
||||
{
|
||||
PROFILER_SCOPE("Renderer::UpdateFogState", "UpdateFogState", MP_ORCHID1);
|
||||
Context &c = getContext();
|
||||
ID3D11DeviceContext *d3d11 = c.m_pDeviceContext;
|
||||
|
||||
float fogParams[4] = {};
|
||||
if (c.fogEnabled)
|
||||
{
|
||||
if (c.fogMode == 1)
|
||||
{
|
||||
fogParams[0] = c.fogFarDistance;
|
||||
fogParams[1] = 1.0f / (c.fogFarDistance - c.fogNearDistance);
|
||||
fogParams[2] = 1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
fogParams[0] = c.fogDensity;
|
||||
fogParams[2] = 2.0f;
|
||||
}
|
||||
}
|
||||
|
||||
const float fogColour[4] = {c.fogColourRed, c.fogColourGreen, c.fogColourBlue, 1.0f};
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE mapped = {};
|
||||
d3d11->Map(c.m_fogParamsBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
|
||||
std::memcpy(mapped.pData, fogParams, sizeof(fogParams));
|
||||
d3d11->Unmap(c.m_fogParamsBuffer, 0);
|
||||
|
||||
d3d11->Map(c.m_fogColourBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
|
||||
std::memcpy(mapped.pData, fogColour, sizeof(fogColour));
|
||||
d3d11->Unmap(c.m_fogColourBuffer, 0);
|
||||
}
|
||||
|
||||
|
||||
void Renderer::UpdateLightingState()
|
||||
{
|
||||
PROFILER_SCOPE("Renderer::UpdateLightingState", "UpdateLightingState", MP_ORCHID1);
|
||||
Context &c = getContext();
|
||||
if (!c.lightingDirty || !c.lightingEnabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!c.lightEnabled[0])
|
||||
{
|
||||
std::memset(&c.lightDirection[0], 0, sizeof(c.lightDirection[0]));
|
||||
std::memset(&c.lightColour[0], 0, sizeof(c.lightColour[0]));
|
||||
}
|
||||
|
||||
if (!c.lightEnabled[1])
|
||||
{
|
||||
std::memset(&c.lightDirection[1], 0, sizeof(c.lightDirection[1]));
|
||||
std::memset(&c.lightColour[1], 0, sizeof(c.lightColour[1]));
|
||||
}
|
||||
|
||||
const std::size_t lightingBytes = sizeof(c.lightDirection) + sizeof(c.lightColour) + sizeof(c.lightAmbientColour);
|
||||
D3D11_MAPPED_SUBRESOURCE mapped = {};
|
||||
c.m_pDeviceContext->Map(c.m_lightingStateBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
|
||||
std::memmove(mapped.pData, c.lightDirection, lightingBytes);
|
||||
c.m_pDeviceContext->Unmap(c.m_lightingStateBuffer, 0);
|
||||
|
||||
c.lightingDirty = false;
|
||||
}
|
||||
|
||||
|
||||
void Renderer::UpdateTexGenState()
|
||||
{
|
||||
PROFILER_SCOPE("Renderer::UpdateTexGenState", "UpdateTexGenState", MP_ORCHID1);
|
||||
Context &c = getContext();
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE mapped = {};
|
||||
c.m_pDeviceContext->Map(c.m_texGenMatricesBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
|
||||
c.m_pDeviceContext->Unmap(c.m_texGenMatricesBuffer, 0);
|
||||
std::memcpy(mapped.pData, c.texGenMatrices, sizeof(c.texGenMatrices));
|
||||
}
|
||||
|
||||
|
||||
void Renderer::UpdateViewportState() {}
|
||||
@@ -0,0 +1,333 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2026 Patoke
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "Renderer.h"
|
||||
#include "libpng/png.h"
|
||||
|
||||
unsigned char* dataStart;
|
||||
unsigned char *dataCurr;
|
||||
unsigned char *dataEnd;
|
||||
|
||||
DXGI_FORMAT Renderer::textureFormats[] = {
|
||||
DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||
DXGI_FORMAT_UNKNOWN
|
||||
};
|
||||
|
||||
// these are here because they are used before they are defined
|
||||
// its fine like that and the order of everything matches ida so we have to put these here
|
||||
void user_flush_data(png_struct_def *png_ptr);
|
||||
void user_write_data(png_struct_def *png_ptr, unsigned char *src, size_t length);
|
||||
|
||||
HRESULT Renderer::LoadTextureData(BYTE* pbData, DWORD dwBytes, D3DXIMAGE_INFO* pSrcInfo, int** ppDataOut)
|
||||
{
|
||||
PROFILER_SCOPE("Renderer::LoadTextureData_Memory", "LoadTextureData_Memory", MP_PURPLE4);
|
||||
png_image image;
|
||||
memset(&image, 0, sizeof(image));
|
||||
image.version = PNG_IMAGE_VERSION;
|
||||
|
||||
png_image_begin_read_from_memory(&image, pbData, dwBytes);
|
||||
|
||||
if (PNG_IMAGE_FAILED(image))
|
||||
return E_FAIL;
|
||||
|
||||
image.format = PNG_FORMAT_BGRA;
|
||||
|
||||
*ppDataOut = new int[image.width * image.height];
|
||||
if (!*ppDataOut || !png_image_finish_read(&image, NULL, *ppDataOut, NULL, NULL))
|
||||
return E_FAIL;
|
||||
|
||||
pSrcInfo->Width = image.width;
|
||||
pSrcInfo->Height = image.height;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT Renderer::LoadTextureData(const char* szFilename, D3DXIMAGE_INFO* pSrcInfo, int** ppDataOut)
|
||||
{
|
||||
PROFILER_SCOPE("Renderer::LoadTextureData_File", "LoadTextureData_File", MP_PURPLE4);
|
||||
png_image image;
|
||||
memset(&image, 0, sizeof(image));
|
||||
image.version = PNG_IMAGE_VERSION;
|
||||
|
||||
png_image_begin_read_from_file(&image, szFilename);
|
||||
|
||||
if (PNG_IMAGE_FAILED(image))
|
||||
return E_FAIL;
|
||||
|
||||
image.format = PNG_FORMAT_BGRA;
|
||||
|
||||
*ppDataOut = new int[image.width * image.height];
|
||||
if (!*ppDataOut || !png_image_finish_read(&image, NULL, *ppDataOut, NULL, NULL))
|
||||
return E_FAIL;
|
||||
|
||||
pSrcInfo->Width = image.width;
|
||||
pSrcInfo->Height = image.height;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT Renderer::SaveTextureData(const char* szFilename, D3DXIMAGE_INFO* pSrcInfo, int* ppDataOut)
|
||||
{
|
||||
PROFILER_SCOPE("Renderer::SaveTextureData", "SaveTextureData", MP_PURPLE4);
|
||||
png_image image;
|
||||
memset(&image, 0, sizeof(image));
|
||||
|
||||
image.width = pSrcInfo->Width;
|
||||
image.height = pSrcInfo->Height;
|
||||
image.version = PNG_IMAGE_VERSION;
|
||||
image.format = PNG_FORMAT_RGBA;
|
||||
|
||||
png_image_write_to_file(&image, szFilename, NULL, ppDataOut, NULL, NULL);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT Renderer::SaveTextureDataToMemory(void* pOutput, int outputCapacity, int* outputLength, int width, int height, int* ppDataIn)
|
||||
{
|
||||
PROFILER_SCOPE("Renderer::SaveTextureDataToMemory", "SaveTextureDataToMemory", MP_PURPLE4);
|
||||
png_image image;
|
||||
memset(&image, 0, sizeof(image));
|
||||
|
||||
image.width = width;
|
||||
image.height = height;
|
||||
dataEnd = (BYTE *)pOutput + outputCapacity;
|
||||
image.version = PNG_IMAGE_VERSION;
|
||||
image.format = PNG_FORMAT_RGBA;
|
||||
dataStart = (BYTE*)pOutput;
|
||||
dataCurr = (BYTE*)pOutput;
|
||||
|
||||
png_image_write_to_stdio(&image, NULL, NULL, ppDataIn, NULL, NULL, user_write_data, user_flush_data);
|
||||
|
||||
*outputLength = (int)(dataCurr - dataStart);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void Renderer::TextureBind(int idx)
|
||||
{
|
||||
PROFILER_SCOPE("Renderer::TextureBind", "TextureBind", MP_PURPLE4);
|
||||
if (idx == -1)
|
||||
idx = defaultTextureIndex;
|
||||
|
||||
Context& c = getContext();
|
||||
|
||||
if (c.commandBuffer && c.commandBuffer->isActive)
|
||||
c.commandBuffer->BindTexture(idx);
|
||||
|
||||
c.textureIdx = idx;
|
||||
c.m_pDeviceContext->PSSetShaderResources(0, 1, &m_textures[idx].view);
|
||||
|
||||
UpdateTextureState(false);
|
||||
}
|
||||
|
||||
void Renderer::TextureBindVertex(int idx)
|
||||
{
|
||||
PROFILER_SCOPE("Renderer::TextureBindVertex", "TextureBindVertex", MP_PURPLE4);
|
||||
if (idx == -1)
|
||||
idx = defaultTextureIndex;
|
||||
|
||||
Context& c = getContext();
|
||||
|
||||
c.textureIdx = idx;
|
||||
c.m_pDeviceContext->VSSetShaderResources(0, 1, &m_textures[idx].view);
|
||||
|
||||
UpdateTextureState(true);
|
||||
}
|
||||
|
||||
int Renderer::TextureCreate()
|
||||
{
|
||||
PROFILER_SCOPE("Renderer::TextureCreate", "TextureCreate", MP_PURPLE4);
|
||||
for (int i = 0; i < MAX_TEXTURES; i++)
|
||||
{
|
||||
if (!m_textures[i].allocated)
|
||||
{
|
||||
m_textures[i].texture = NULL;
|
||||
m_textures[i].allocated = true;
|
||||
m_textures[i].mipLevels = 1;
|
||||
m_textures[i].samplerParams = 0;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Renderer::TextureData(int width, int height, void* data, int level, C4JRender::eTextureFormat format)
|
||||
{
|
||||
PROFILER_SCOPE("Renderer::TextureData", "TextureData", MP_PURPLE4);
|
||||
Context& c = getContext();
|
||||
int idx = c.textureIdx;
|
||||
|
||||
m_textures[idx].textureFormat = format;
|
||||
|
||||
if (level == 0)
|
||||
{
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
desc.Width = width;
|
||||
desc.Height = height;
|
||||
desc.MipLevels = m_textures[idx].mipLevels;
|
||||
desc.ArraySize = 1;
|
||||
desc.Format = textureFormats[format];
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
desc.CPUAccessFlags = 0;
|
||||
desc.MiscFlags = 0;
|
||||
|
||||
m_pDevice->CreateTexture2D(&desc, NULL, &m_textures[idx].texture);
|
||||
m_pDevice->CreateShaderResourceView(m_textures[idx].texture, NULL, &m_textures[idx].view);
|
||||
}
|
||||
|
||||
c.m_pDeviceContext->UpdateSubresource(
|
||||
m_textures[idx].texture,
|
||||
level,
|
||||
NULL,
|
||||
data,
|
||||
static_cast<UINT>(width * 4),
|
||||
static_cast<UINT>(width * height * 4)
|
||||
);
|
||||
}
|
||||
|
||||
void Renderer::TextureDataUpdate(int xoffset, int yoffset, int width, int height, void* data, int level)
|
||||
{
|
||||
PROFILER_SCOPE("Renderer::TextureDataUpdate", "TextureDataUpdate", MP_PURPLE4);
|
||||
Context& c = getContext();
|
||||
int idx = c.textureIdx;
|
||||
|
||||
D3D11_TEXTURE2D_DESC desc = {};
|
||||
m_textures[idx].texture->GetDesc(&desc);
|
||||
|
||||
D3D11_BOX box = {};
|
||||
box.left = xoffset;
|
||||
box.top = yoffset;
|
||||
box.right = xoffset + width;
|
||||
box.bottom = yoffset + height;
|
||||
box.front = 0;
|
||||
box.back = 1;
|
||||
|
||||
c.m_pDeviceContext->UpdateSubresource(
|
||||
m_textures[idx].texture,
|
||||
level,
|
||||
&box,
|
||||
data,
|
||||
static_cast<UINT>(width * 4),
|
||||
static_cast<UINT>(width * height * 4)
|
||||
);
|
||||
}
|
||||
|
||||
void Renderer::TextureDynamicUpdateEnd() {}
|
||||
void Renderer::TextureDynamicUpdateStart() {}
|
||||
|
||||
void Renderer::TextureFree(int idx)
|
||||
{
|
||||
PROFILER_SCOPE("Renderer::TextureFree", "TextureFree", MP_PURPLE4);
|
||||
m_textures[idx].texture->Release();
|
||||
m_textures[idx].view->Release();
|
||||
m_textures[idx].view = NULL;
|
||||
m_textures[idx].allocated = false;
|
||||
m_textures[idx].texture = NULL;
|
||||
}
|
||||
|
||||
void Renderer::TextureGetStats() {}
|
||||
|
||||
ID3D11ShaderResourceView* Renderer::TextureGetTexture(int idx)
|
||||
{
|
||||
if (idx < MAX_TEXTURES) {
|
||||
if (m_textures[idx].allocated) return m_textures[idx].view;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int Renderer::TextureGetTextureLevels()
|
||||
{
|
||||
Context& c = getContext();
|
||||
return m_textures[c.textureIdx].mipLevels;
|
||||
}
|
||||
|
||||
void Renderer::TextureSetParam(int param, int value)
|
||||
{
|
||||
Context& c = getContext();
|
||||
int idx = c.textureIdx;
|
||||
|
||||
switch (param)
|
||||
{
|
||||
case GL_TEXTURE_MIN_FILTER:
|
||||
m_textures[idx].samplerParams &= ~4u;
|
||||
if (value == GL_LINEAR)
|
||||
m_textures[idx].samplerParams |= 4u;
|
||||
break;
|
||||
case GL_TEXTURE_MAG_FILTER:
|
||||
m_textures[idx].samplerParams &= ~8u;
|
||||
if (value == GL_LINEAR)
|
||||
m_textures[idx].samplerParams |= 8u;
|
||||
break;
|
||||
case GL_TEXTURE_WRAP_S:
|
||||
m_textures[idx].samplerParams &= ~1u;
|
||||
if (value == GL_CLAMP)
|
||||
m_textures[idx].samplerParams |= 1u;
|
||||
break;
|
||||
case GL_TEXTURE_WRAP_T:
|
||||
m_textures[idx].samplerParams &= ~2u;
|
||||
if (value == GL_CLAMP)
|
||||
m_textures[idx].samplerParams |= 2u;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::TextureSetTextureLevels(int levels)
|
||||
{
|
||||
Context& c = getContext();
|
||||
m_textures[c.textureIdx].mipLevels = levels;
|
||||
}
|
||||
|
||||
void Renderer::UpdateTextureState(bool bVertex)
|
||||
{
|
||||
Context& c = getContext();
|
||||
ID3D11SamplerState* pSampler = GetManagedSamplerState();
|
||||
|
||||
if (bVertex)
|
||||
c.m_pDeviceContext->VSSetSamplers(0, 1, &pSampler);
|
||||
else
|
||||
c.m_pDeviceContext->PSSetSamplers(0, 1, &pSampler);
|
||||
}
|
||||
|
||||
void user_flush_data(png_struct_def* png_ptr) {}
|
||||
void user_write_data(png_struct_def* png_ptr, unsigned char* src, size_t length)
|
||||
{
|
||||
int bytesToWrite = static_cast<int>(dataEnd - dataCurr);
|
||||
if (static_cast<int>(length) < bytesToWrite)
|
||||
bytesToWrite = (int)length;
|
||||
|
||||
std::memcpy(dataCurr, src, bytesToWrite);
|
||||
dataCurr += bytesToWrite;
|
||||
}
|
||||
|
||||
int user_write_data_bytes_written()
|
||||
{
|
||||
return static_cast<int>(dataCurr - dataStart);
|
||||
}
|
||||
|
||||
void user_write_data_init(unsigned char* pBuffer, int size)
|
||||
{
|
||||
dataStart = pBuffer;
|
||||
dataCurr = pBuffer;
|
||||
dataEnd = pBuffer + size;
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2026 Patoke
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "Renderer.h"
|
||||
|
||||
void Renderer::DrawVertexBuffer(C4JRender::ePrimitiveType PrimitiveType, int count, ID3D11Buffer *buffer, C4JRender::eVertexType vType,
|
||||
C4JRender::ePixelShaderType psType)
|
||||
{
|
||||
PROFILER_SCOPE("Renderer::DrawVertexBuffer", "DrawVertexBuffer", MP_RED2);
|
||||
Renderer::Context &c = getContext();
|
||||
ID3D11DeviceContext *d3d11 = c.m_pDeviceContext;
|
||||
|
||||
int drawCount = count;
|
||||
bool indexed = false;
|
||||
|
||||
PROFILER_SCOPE("Renderer::DrawVertexBuffer", "DrawVertexSetup", MP_RED2);
|
||||
DrawVertexSetup(vType, psType, PrimitiveType, &drawCount, &indexed);
|
||||
StateUpdate();
|
||||
|
||||
const UINT stride = vertexStrideTable[vType];
|
||||
const UINT offset = 0;
|
||||
d3d11->IASetVertexBuffers(0, 1, &buffer, &stride, &offset);
|
||||
|
||||
if (indexed)
|
||||
d3d11->DrawIndexed(drawCount, 0, 0);
|
||||
else
|
||||
d3d11->Draw(count, 0);
|
||||
}
|
||||
|
||||
void Renderer::DrawVertexSetup(C4JRender::eVertexType vType, C4JRender::ePixelShaderType psType, C4JRender::ePrimitiveType PrimitiveType, int *count,
|
||||
bool *indexed)
|
||||
{
|
||||
PROFILER_SCOPE("Renderer::DrawVertexSetup", "DrawVertexSetup", MP_RED2);
|
||||
Renderer::Context &c = getContext();
|
||||
ID3D11DeviceContext *d3d11 = c.m_pDeviceContext;
|
||||
|
||||
C4JRender::eVertexType effectiveVertexType = vType;
|
||||
if (effectiveVertexType == C4JRender::VERTEX_TYPE_PF3_TF2_CB4_NB4_XW1 && c.lightingEnabled)
|
||||
effectiveVertexType = C4JRender::VERTEX_TYPE_PF3_TF2_CB4_NB4_XW1_LIT;
|
||||
|
||||
if (effectiveVertexType != activeVertexType)
|
||||
{
|
||||
d3d11->VSSetShader(vertexShaderTable[effectiveVertexType], NULL, 0);
|
||||
d3d11->IASetInputLayout(inputLayoutTable[effectiveVertexType]);
|
||||
activeVertexType = effectiveVertexType;
|
||||
}
|
||||
|
||||
if (psType != activePixelType)
|
||||
{
|
||||
d3d11->PSSetShader(pixelShaderTable[psType], NULL, 0);
|
||||
activePixelType = psType;
|
||||
}
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE mapped = {};
|
||||
|
||||
if (c.matrixDirty[MATRIX_MODE_MODELVIEW])
|
||||
{
|
||||
d3d11->Map(c.m_modelViewMatrix, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
|
||||
memcpy(mapped.pData, MatrixGet(MATRIX_MODE_MODELVIEW), sizeof(DirectX::XMMATRIX));
|
||||
d3d11->Unmap(c.m_modelViewMatrix, 0);
|
||||
c.matrixDirty[MATRIX_MODE_MODELVIEW] = false;
|
||||
}
|
||||
|
||||
if (c.matrixDirty[MATRIX_MODE_MODELVIEW_PROJECTION])
|
||||
{
|
||||
d3d11->Map(c.m_projectionMatrix, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
|
||||
memcpy(mapped.pData, MatrixGet(MATRIX_MODE_MODELVIEW_PROJECTION), sizeof(DirectX::XMMATRIX));
|
||||
d3d11->Unmap(c.m_projectionMatrix, 0);
|
||||
c.matrixDirty[MATRIX_MODE_MODELVIEW_PROJECTION] = false;
|
||||
}
|
||||
|
||||
if (c.matrixDirty[MATRIX_MODE_MODELVIEW_TEXTURE])
|
||||
{
|
||||
d3d11->Map(c.m_textureMatrix, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
|
||||
memcpy(mapped.pData, MatrixGet(MATRIX_MODE_MODELVIEW_TEXTURE), sizeof(DirectX::XMMATRIX));
|
||||
d3d11->Unmap(c.m_textureMatrix, 0);
|
||||
c.matrixDirty[MATRIX_MODE_MODELVIEW_TEXTURE] = false;
|
||||
}
|
||||
|
||||
UpdateFogState();
|
||||
UpdateViewportState();
|
||||
UpdateLightingState();
|
||||
UpdateTexGenState();
|
||||
|
||||
d3d11->IASetPrimitiveTopology(g_topologies[PrimitiveType]);
|
||||
|
||||
if (PrimitiveType == C4JRender::PRIMITIVE_TYPE_QUAD_LIST)
|
||||
{
|
||||
d3d11->IASetIndexBuffer(quadIndexBuffer, DXGI_FORMAT_R16_UINT, 0);
|
||||
*count = (*count * 6) / 4;
|
||||
*indexed = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (PrimitiveType == C4JRender::PRIMITIVE_TYPE_TRIANGLE_FAN)
|
||||
{
|
||||
d3d11->IASetIndexBuffer(fanIndexBuffer, DXGI_FORMAT_R16_UINT, 0);
|
||||
*count = (*count - 2) * 3;
|
||||
*indexed = true;
|
||||
return;
|
||||
}
|
||||
|
||||
d3d11->IASetIndexBuffer(NULL, DXGI_FORMAT_R16_UINT, 0);
|
||||
*indexed = false;
|
||||
}
|
||||
|
||||
void Renderer::DrawVertices(C4JRender::ePrimitiveType PrimitiveType, int count, void *vertices, C4JRender::eVertexType vType,
|
||||
C4JRender::ePixelShaderType psType)
|
||||
{
|
||||
PROFILER_SCOPE("Renderer::DrawVertices", "DrawVertices", MP_RED2);
|
||||
Renderer::Context &c = getContext();
|
||||
ID3D11DeviceContext *d3d11 = c.m_pDeviceContext;
|
||||
Renderer::CommandBuffer *commandBuffer = c.commandBuffer;
|
||||
|
||||
if (commandBuffer != NULL)
|
||||
{
|
||||
C4JRender::eVertexType effectiveVertexType = vType;
|
||||
if (effectiveVertexType == C4JRender::VERTEX_TYPE_PF3_TF2_CB4_NB4_XW1 && c.lightingEnabled)
|
||||
effectiveVertexType = C4JRender::VERTEX_TYPE_PF3_TF2_CB4_NB4_XW1_LIT;
|
||||
|
||||
c.recordingPrimitiveType = PrimitiveType;
|
||||
c.recordingVertexType = effectiveVertexType;
|
||||
const UINT stride = vertexStrideTable[effectiveVertexType];
|
||||
commandBuffer->AddVertices(stride, static_cast<UINT>(count), vertices, c);
|
||||
return;
|
||||
}
|
||||
|
||||
int drawCount = count;
|
||||
bool indexed = false;
|
||||
|
||||
PROFILER_SCOPE("Renderer::DrawVertices", "DrawVertexSetup", MP_RED2);
|
||||
DrawVertexSetup(vType, psType, PrimitiveType, &drawCount, &indexed);
|
||||
|
||||
const UINT stride = vertexStrideTable[vType];
|
||||
const UINT vertexBytes = stride * static_cast<UINT>(count);
|
||||
|
||||
assert(vertexBytes <= Context::VERTEX_BUFFER_SIZE);
|
||||
|
||||
UINT vertexOffset = c.dynamicVertexOffset;
|
||||
if (vertexOffset + vertexBytes > Context::VERTEX_BUFFER_SIZE)
|
||||
vertexOffset = 0;
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE mapped = {};
|
||||
const D3D11_MAP mapType = vertexOffset == 0 ? D3D11_MAP_WRITE_DISCARD : D3D11_MAP_WRITE_NO_OVERWRITE;
|
||||
const HRESULT hr = d3d11->Map(c.dynamicVertexBuffer, 0, mapType, 0, &mapped);
|
||||
if (FAILED(hr))
|
||||
printf("ERROR: 0x%x\n", static_cast<unsigned int>(hr));
|
||||
|
||||
memcpy(reinterpret_cast<std::uint8_t *>(mapped.pData) + vertexOffset, vertices, vertexBytes);
|
||||
d3d11->Unmap(c.dynamicVertexBuffer, 0);
|
||||
|
||||
StateUpdate();
|
||||
|
||||
ID3D11Buffer *dynamicBuffer = c.dynamicVertexBuffer;
|
||||
d3d11->IASetVertexBuffers(0, 1, &dynamicBuffer, &stride, &vertexOffset);
|
||||
|
||||
if (indexed)
|
||||
d3d11->DrawIndexed(drawCount, 0, 0);
|
||||
else
|
||||
d3d11->Draw(count, 0);
|
||||
|
||||
c.dynamicVertexOffset = vertexOffset + vertexBytes;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2026 Patoke
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
Reference in New Issue
Block a user