main: add 3d volume visualization

This commit is contained in:
Zack Buhman 2026-01-12 16:00:00 -06:00
parent 7939bb8b97
commit 83338bada4
8 changed files with 306 additions and 36 deletions

View File

@ -9,6 +9,7 @@ all: $(BUILD_TYPE)/d3d10.exe
SHADERS = \
main.fxo \
font.fxo \
volume.fxo \
bloom.fxo \
static.fxo

View File

@ -70,7 +70,7 @@ float4 PS(PS_INPUT input) : SV_Target
return float4(c.xxx, 1);
}
BlendState Blending
BlendState EnableBlending
{
BlendEnable[0] = TRUE;
SrcBlend = ONE;
@ -94,7 +94,7 @@ technique10 Font
SetVertexShader(CompileShader(vs_4_0, VS()));
SetGeometryShader(CompileShader(gs_4_0, GS()));
SetPixelShader(CompileShader(ps_4_0, PS()));
SetBlendState(Blending, float4(0.0, 0.0, 0.0, 0.0), 0xffffffff);
SetBlendState(EnableBlending, float4(0.0, 0.0, 0.0, 0.0), 0xffffffff);
SetDepthStencilState(DisableDepth, 0);
}
}

View File

@ -1,12 +1,21 @@
#ifndef _RENDER_STATE_HPP_
#define _RENDER_STATE_HPP_
HRESULT LoadTexture(const wchar_t * resourceName,
const int width,
const int height,
const int pitch,
const DXGI_FORMAT format,
ID3D10ShaderResourceView ** pTextureShaderResourceView);
HRESULT LoadTexture2D(const wchar_t * resourceName,
const int width,
const int height,
const int pitch,
const DXGI_FORMAT format,
ID3D10ShaderResourceView ** pTextureShaderResourceView);
HRESULT LoadTexture3D(const wchar_t * resourceName,
const int width,
const int height,
const int depth,
const int pitch,
const int slicePitch,
const DXGI_FORMAT format,
ID3D10ShaderResourceView ** pTextureShaderResourceView);
HRESULT CreateTextureRenderTargetView(const int width,
const int height,

View File

@ -1,6 +1,8 @@
RES_MAIN_FXO RCDATA "main.fxo"
RES_FONT_FXO RCDATA "font.fxo"
RES_VOLUME_FXO RCDATA "volume.fxo"
RES_BLOOM_FXO RCDATA "bloom.fxo"
RES_STATIC_FXO RCDATA "static.fxo"
RES_PERLIN RCDATA "texture/perlin.data"
RES_ROBOT_PLAYER RCDATA "models/robot_player/robot_player.data"
RES_FONT_TERMINUS_6X12 RCDATA "font/terminus_128x64_6x12.data"

View File

@ -84,6 +84,16 @@ ID3D10EffectShaderResourceVariable * g_pDiffuseVariableFont = NULL;
const int g_iFontBufferLength = 512;
typedef D3DXVECTOR4 FontVertex;
// perlin
ID3D10Effect * g_pEffectVolume = NULL;
ID3D10EffectTechnique * g_pTechniqueVolume = NULL;
ID3D10InputLayout * g_pVertexLayoutVolume = NULL;
const DWORD g_dwVertexBufferCountVolume = 1;
ID3D10Buffer * g_pVertexBuffersVolume[g_dwVertexBufferCountVolume];
ID3D10ShaderResourceView * g_pTextureShaderResourceViewPerlin = NULL;
ID3D10EffectScalarVariable * g_pLayerVariableVolume = NULL;
ID3D10EffectShaderResourceVariable * g_pDiffuseVariableVolume = NULL;
// static
ID3D10Effect * g_pEffectStatic = NULL;
ID3D10EffectTechnique * g_pTechniqueStatic = NULL;
@ -200,7 +210,7 @@ HRESULT InitWindow(HINSTANCE hInstance, int nCmdShow)
return E_FAIL;
// create window
RECT rc = { 0, 0, 160, 120 };
RECT rc = { 0, 0, 512, 512 };
AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE);
UINT width = rc.right - rc.left;
UINT height = rc.bottom - rc.top;
@ -420,25 +430,38 @@ HRESULT LoadMesh()
// textures
//////////////////////////////////////////////////////////////////////
hr = LoadTexture(L"RES_ROBOT_PLAYER",
64, // width
64, // height
64 * 4, // pitch
DXGI_FORMAT_R8G8B8A8_UNORM,
&g_pTextureShaderResourceView);
hr = LoadTexture2D(L"RES_ROBOT_PLAYER",
64, // width
64, // height
64 * 4, // pitch
DXGI_FORMAT_R8G8B8A8_UNORM,
&g_pTextureShaderResourceView);
if (FAILED(hr)) {
print("LoadTexture\n");
print("LoadTexture2D\n");
return hr;
}
hr = LoadTexture(L"RES_FONT_TERMINUS_6X12",
g_FontSize.Texture.Width, // width
g_FontSize.Texture.Height, // height
g_FontSize.Texture.Width * 1, // pitch
DXGI_FORMAT_R8_UNORM,
&g_pTextureShaderResourceViewFont);
hr = LoadTexture2D(L"RES_FONT_TERMINUS_6X12",
g_FontSize.Texture.Width, // width
g_FontSize.Texture.Height, // height
g_FontSize.Texture.Width * 1, // pitch
DXGI_FORMAT_R8_UNORM,
&g_pTextureShaderResourceViewFont);
if (FAILED(hr)) {
print("LoadTexture\n");
print("LoadTexture2D\n");
return hr;
}
hr = LoadTexture3D(L"RES_PERLIN",
256, // width
256, // height
256, // depth
256 * 1, // pitch
256 * 256 * 1, // slicePitch
DXGI_FORMAT_R8_UNORM,
&g_pTextureShaderResourceViewPerlin);
if (FAILED(hr)) {
print("LoadTexture2D\n");
return hr;
}
@ -522,6 +545,91 @@ HRESULT InitFontBuffers()
return S_OK;
}
HRESULT InitVolumeBuffers()
{
HRESULT hr;
//////////////////////////////////////////////////////////////////////
// effect
//////////////////////////////////////////////////////////////////////
HRSRC hRes = FindResource(NULL, L"RES_VOLUME_FXO", RT_RCDATA);
if (hRes == NULL) {
print("FindResource RES_VOLUME_FXO\n");
return E_FAIL;
}
DWORD dwResSize = SizeofResource(NULL, hRes);
HGLOBAL hData = LoadResource(NULL, hRes);
void * pData = LockResource(hData);
hr = D3D10CreateEffectFromMemory(pData,
dwResSize,
0,
g_pd3dDevice,
NULL,
&g_pEffectVolume
);
if (FAILED(hr)) {
print("D3D10CreateEffectFromMemory\n");
return hr;
}
g_pTechniqueVolume = g_pEffectVolume->GetTechniqueByName("Volume");
g_pLayerVariableVolume = g_pEffectVolume->GetVariableByName("layer")->AsScalar();
g_pDiffuseVariableVolume = g_pEffectVolume->GetVariableByName("txDiffuse")->AsShaderResource();
assert(g_pDiffuseVariableVolume != NULL);
//////////////////////////////////////////////////////////////////////
// layout
//////////////////////////////////////////////////////////////////////
D3D10_INPUT_ELEMENT_DESC layout[] = {
{"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0 , D3D10_INPUT_PER_VERTEX_DATA, 0},
};
UINT numElements = (sizeof (layout)) / (sizeof (layout[0]));
D3D10_PASS_DESC passDesc;
g_pTechniqueVolume->GetPassByIndex(0)->GetDesc(&passDesc);
hr = g_pd3dDevice->CreateInputLayout(layout, numElements,
passDesc.pIAInputSignature,
passDesc.IAInputSignatureSize,
&g_pVertexLayoutVolume);
if (FAILED(hr)) {
print("CreateInputLayout\n");
return hr;
}
//////////////////////////////////////////////////////////////////////
// vertex buffers
//////////////////////////////////////////////////////////////////////
D3D10_BUFFER_DESC bd;
D3D10_SUBRESOURCE_DATA initData;
const D3DXVECTOR2 position[] = {
D3DXVECTOR2(-1, 1),
D3DXVECTOR2( 1, 1),
D3DXVECTOR2(-1, -1),
D3DXVECTOR2( 1, -1),
};
// position
bd.Usage = D3D10_USAGE_DEFAULT;
bd.ByteWidth = (sizeof (D3DXVECTOR2)) * 4;
bd.BindFlags = D3D10_BIND_VERTEX_BUFFER;
bd.CPUAccessFlags = 0;
bd.MiscFlags = 0;
initData.pSysMem = position;
hr = g_pd3dDevice->CreateBuffer(&bd, &initData, &g_pVertexBuffersVolume[0]);
if (FAILED(hr)) {
print("CreateBuffer\n");
return hr;
}
return S_OK;
}
// +Y is up
D3DXVECTOR2 vtxBloom[] = {
D3DXVECTOR2(-1, -1), // top left
@ -900,6 +1008,12 @@ HRESULT InitDirect3DDevice()
return hr;
}
hr = InitVolumeBuffers();
if (FAILED(hr)) {
print("InitVolumeBuffers\n");
return hr;
}
hr = InitBloomBuffers();
if (FAILED(hr)) {
print("InitBloomBuffers\n");
@ -1427,6 +1541,30 @@ void Update(float t)
D3DXVec3Transform(&g_vLightDirs[0], (D3DXVECTOR3 *)&vLightDirs[0], &mRotate);
}
void RenderVolume(float t)
{
UINT stride[] = {
(sizeof (D3DXVECTOR2)),
};
UINT offset[] = { 0 };
g_pd3dDevice->IASetInputLayout(g_pVertexLayoutVolume);
g_pd3dDevice->IASetVertexBuffers(0, g_dwVertexBufferCountVolume, g_pVertexBuffersVolume, stride, offset);
g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
g_pLayerVariableVolume->SetFloat(t * 0.002f);
g_pDiffuseVariableVolume->SetResource(g_pTextureShaderResourceViewPerlin);
D3D10_TECHNIQUE_DESC techDescVolume;
g_pTechniqueVolume->GetDesc(&techDescVolume);
g_pd3dDevice->OMSetRenderTargets(1, &g_pRenderTargetView, NULL);
for (UINT p = 0; p < techDescVolume.Passes; p++) {
g_pTechniqueVolume->GetPassByIndex(p)->Apply(0);
g_pd3dDevice->Draw(4, 0);
}
}
void Render()
{
static float t = 0.0f;
@ -1450,6 +1588,7 @@ void Render()
g_pd3dDevice->ClearDepthStencilView(g_pDepthStencilView, D3D10_CLEAR_DEPTH, 1.0f, 0);
// render
/*
RenderModel(t);
RenderFont();
@ -1463,6 +1602,8 @@ void Render()
RenderMeshStatic(cube::node_0.mesh, t);
RenderBloom();
*/
RenderVolume(t);
// present
g_pSwapChain->Present(0, 0);

View File

@ -8,28 +8,28 @@
#include "print.hpp"
#include "render_state.hpp"
HRESULT LoadTexture(const wchar_t * resourceName,
const int width,
const int height,
const int pitch,
const DXGI_FORMAT format,
ID3D10ShaderResourceView ** pTextureShaderResourceView)
HRESULT LoadTexture2D(const wchar_t * resourceName,
const int width,
const int height,
const int pitch,
const DXGI_FORMAT format,
ID3D10ShaderResourceView ** pTextureShaderResourceView)
{
HRESULT hr;
// texture
HRSRC hRobotPlayerRes = FindResource(NULL, resourceName, RT_RCDATA);
if (hRobotPlayerRes == NULL) {
print("FindResource %s\n");
HRSRC hRes = FindResource(NULL, resourceName, RT_RCDATA);
if (hRes == NULL) {
print("FindResource %s\n", resourceName);
return -1;
}
DWORD dwResourceSize = SizeofResource(NULL, hRobotPlayerRes);
DWORD dwResourceSize = SizeofResource(NULL, hRes);
assert(pitch >= width);
assert(pitch * height == dwResourceSize);
HGLOBAL hRobotPlayerData = LoadResource(NULL, hRobotPlayerRes);
HGLOBAL hData = LoadResource(NULL, hRes);
D3D10_SUBRESOURCE_DATA subresourceData;
subresourceData.pSysMem = LockResource(hRobotPlayerData);
subresourceData.pSysMem = LockResource(hData);
subresourceData.SysMemPitch = pitch;
D3D10_TEXTURE2D_DESC textureDesc;
textureDesc.Width = width;
@ -45,7 +45,6 @@ HRESULT LoadTexture(const wchar_t * resourceName,
textureDesc.MiscFlags = 0;
ID3D10Texture2D * pTexture;
hr = g_pd3dDevice->CreateTexture2D(&textureDesc, &subresourceData, &pTexture);
if (FAILED(hr)) {
print("CreateTexture2D\n");
@ -66,6 +65,65 @@ HRESULT LoadTexture(const wchar_t * resourceName,
return S_OK;
}
HRESULT LoadTexture3D(const wchar_t * resourceName,
const int width,
const int height,
const int depth,
const int pitch,
const int slicePitch,
const DXGI_FORMAT format,
ID3D10ShaderResourceView ** pTextureShaderResourceView)
{
HRESULT hr;
HRSRC hRes = FindResource(NULL, resourceName, RT_RCDATA);
if (hRes == NULL) {
print("FindResource %s\n", resourceName);
return -1;
}
DWORD dwResourceSize = SizeofResource(NULL, hRes);
assert(pitch >= width);
assert(slicePitch >= depth);
assert(slicePitch * depth == dwResourceSize);
HGLOBAL hData = LoadResource(NULL, hRes);
D3D10_SUBRESOURCE_DATA subresourceData;
subresourceData.pSysMem = LockResource(hData);
subresourceData.SysMemPitch = pitch;
subresourceData.SysMemSlicePitch = slicePitch;
D3D10_TEXTURE3D_DESC textureDesc;
textureDesc.Width = width;
textureDesc.Height = height;
textureDesc.Depth = depth;
textureDesc.MipLevels = 1;
textureDesc.Format = format;
textureDesc.Usage = D3D10_USAGE_IMMUTABLE;
textureDesc.BindFlags = D3D10_BIND_SHADER_RESOURCE;
textureDesc.CPUAccessFlags = 0;
textureDesc.MiscFlags = 0;
ID3D10Texture3D * pTexture;
hr = g_pd3dDevice->CreateTexture3D(&textureDesc, &subresourceData, &pTexture);
if (FAILED(hr)) {
print("CreateTexture3D\n");
return hr;
}
D3D10_SHADER_RESOURCE_VIEW_DESC descSRV;
descSRV.Format = textureDesc.Format;
descSRV.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE3D;
descSRV.Texture3D.MostDetailedMip = 0;
descSRV.Texture3D.MipLevels = 1;
hr = g_pd3dDevice->CreateShaderResourceView(pTexture, &descSRV, pTextureShaderResourceView);
if (FAILED(hr)) {
print("CreateShaderResourceView\n");
return hr;
}
return S_OK;
}
HRESULT CreateTextureRenderTargetView(const int width,
const int height,
ID3D10RenderTargetView ** pRenderTargetView,

1
texture/perlin.data Normal file

File diff suppressed because one or more lines are too long

58
volume.fx Normal file
View File

@ -0,0 +1,58 @@
float layer;
Texture3D txDiffuse;
SamplerState samPoint {
Filter = MIN_MAG_MIP_LINEAR;
AddressU = Wrap;
AddressV = Wrap;
};
struct VS_INPUT
{
float4 Pos : POSITION;
};
struct PS_INPUT
{
float4 Pos : SV_POSITION;
float2 Tex : TEXCOORD0;
};
PS_INPUT VS(VS_INPUT input)
{
PS_INPUT output;
output.Pos = float4(input.Pos.xy, 0, 1);
output.Tex = input.Pos.xy * float2(0.5, -0.5) + float2(0.5, 0.5);
return output;
}
float4 PS(PS_INPUT input) : SV_Target
{
float4 texColor = txDiffuse.Sample(samPoint, float3(input.Tex.xy, layer));
return float4(texColor.xxx, 1);
}
BlendState DisableBlending
{
BlendEnable[0] = False;
};
DepthStencilState DisableDepth
{
DepthEnable = FALSE;
DepthWriteMask = ZERO;
};
technique10 Volume
{
pass P0
{
SetVertexShader(CompileShader(vs_4_0, VS()));
SetGeometryShader(NULL);
SetPixelShader(CompileShader(ps_4_0, PS()));
SetBlendState(DisableBlending, float4(0.0, 0.0, 0.0, 0.0), 0xffffffff);
SetDepthStencilState(DisableDepth, 0);
}
}