More dxPtexViewer improvements:

- fullscreen mode added (-f)
- added usage error message
- added IBL lighting
- matched GUI to glPtexViewer
- removed some ptex HW filter options (missing code is causing crash)

Note : the IBL BRDF definitely needs some tweaks...
This commit is contained in:
manuelk 2016-02-25 17:14:09 -08:00
parent 84d0e02fa2
commit b5cabd2259
6 changed files with 682 additions and 56 deletions

View File

@ -26,6 +26,7 @@
set(SHADER_FILES
shader.hlsl
skyshader.hlsl
)
set(PLATFORM_LIBRARIES
@ -56,6 +57,7 @@ endif()
set(SOURCE_FILES
dxPtexViewer.cpp
sky.cpp
)
_stringify("${SHADER_FILES}" INC_FILES)

View File

@ -58,6 +58,8 @@
#include <osd/d3d11Mesh.h>
OpenSubdiv::Osd::D3D11MeshInterface *g_mesh;
#include "./sky.h"
#include "Ptexture.h"
#include "PtexUtils.h"
@ -67,6 +69,7 @@ OpenSubdiv::Osd::D3D11MeshInterface *g_mesh;
#include "../common/d3d11Hud.h"
#include "../common/d3d11PtexMipmapTexture.h"
#include "../common/d3d11ShaderCache.h"
#include "../common/hdr_reader.h"
#include <osd/hlslPatchShaderSource.h>
static const char *g_shaderSource =
@ -207,6 +210,8 @@ std::vector<float> g_positions,
std::vector<std::vector<float> > g_animPositions;
Sky * g_sky=0;
D3D11PtexMipmapTexture * g_osdPTexImage = 0;
D3D11PtexMipmapTexture * g_osdPTexDisplacement = 0;
D3D11PtexMipmapTexture * g_osdPTexOcclusion = 0;
@ -220,19 +225,63 @@ IDXGISwapChain * g_pSwapChain = NULL;
ID3D11RenderTargetView * g_pSwapChainRTV = NULL;
ID3D11RasterizerState* g_pRasterizerState = NULL;
ID3D11InputLayout* g_pInputLayout = NULL;
ID3D11DepthStencilState* g_pDepthStencilState = NULL;
ID3D11InputLayout * g_pInputLayout = NULL;
ID3D11DepthStencilState * g_pDepthStencilState = NULL;
ID3D11Texture2D * g_pDepthStencilBuffer = NULL;
ID3D11Buffer* g_pcbPerFrame = NULL;
ID3D11Buffer* g_pcbTessellation = NULL;
ID3D11Buffer* g_pcbLighting = NULL;
ID3D11Buffer* g_pcbConfig = NULL;
ID3D11DepthStencilView* g_pDepthStencilView = NULL;
ID3D11Buffer * g_pcbPerFrame = NULL;
ID3D11Buffer * g_pcbTessellation = NULL;
ID3D11Buffer * g_pcbLighting = NULL;
ID3D11Buffer * g_pcbConfig = NULL;
ID3D11DepthStencilView * g_pDepthStencilView = NULL;
ID3D11Texture2D * g_diffuseEnvironmentMap = NULL;
ID3D11ShaderResourceView * g_diffuseEnvironmentSRV = NULL;
ID3D11Texture2D * g_specularEnvironmentMap = NULL;
ID3D11ShaderResourceView * g_specularEnvironmentSRV = NULL;
ID3D11SamplerState * g_iblSampler = NULL;
ID3D11Query * g_pipelineStatsQuery = NULL;
bool g_bDone = false;
//------------------------------------------------------------------------------
static ID3D11Texture2D *
createHDRTexture(ID3D11Device * device, char const * hdrFile) {
HdrInfo info;
unsigned char * image = loadHdr(hdrFile, &info, /*convertToFloat=*/true);
if (image) {
D3D11_TEXTURE2D_DESC texDesc;
ZeroMemory(&texDesc, sizeof(texDesc));
texDesc.Width = info.width;
texDesc.Height = info.height;
texDesc.MipLevels = 1;
texDesc.ArraySize = 1;
texDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
texDesc.SampleDesc.Count = 1;
texDesc.SampleDesc.Quality = 0;
texDesc.Usage = D3D11_USAGE_DEFAULT;
texDesc.BindFlags = D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE;
texDesc.CPUAccessFlags = 0;
texDesc.MiscFlags = 0;
D3D11_SUBRESOURCE_DATA subData;
subData.pSysMem = (void *)image;
subData.SysMemPitch = info.width * 4 * sizeof(float);
ID3D11Texture2D * texture=0;
device->CreateTexture2D(&texDesc, &subData, &texture);
free(image);
return texture;
}
return 0;
}
//------------------------------------------------------------------------------
static void
calcNormals(OpenSubdiv::Far::TopologyRefiner * refiner,
@ -409,6 +458,7 @@ createPTexGeo(PtexTexture * r) {
}
}
g_size=0.0f;
for (int j = 0; j < 3; ++j) {
g_center[j] = (min[j] + max[j]) * 0.5f;
g_size += (max[j]-min[j])*(max[j]-min[j]);
@ -876,6 +926,7 @@ bindProgram(Effect effect, OpenSubdiv::Osd::PatchArray const & patch) {
float ModelViewMatrix[16];
float ProjectionMatrix[16];
float ModelViewProjectionMatrix[16];
float ModelViewInverseMatrix[16];
};
if (! g_pcbPerFrame) {
@ -906,7 +957,8 @@ bindProgram(Effect effect, OpenSubdiv::Osd::PatchArray const & patch) {
multMatrix(pData->ModelViewProjectionMatrix,
pData->ModelViewMatrix,
pData->ProjectionMatrix);
inverseMatrix(pData->ModelViewInverseMatrix,
pData->ModelViewMatrix);
g_pd3dDeviceContext->Unmap( g_pcbPerFrame, 0 );
}
@ -1014,6 +1066,19 @@ bindProgram(Effect effect, OpenSubdiv::Osd::PatchArray const & patch) {
g_pd3dDeviceContext->PSSetShaderResources(10, 1, g_osdPTexSpecular->GetTexelsSRV());
g_pd3dDeviceContext->PSSetShaderResources(11, 1, g_osdPTexSpecular->GetLayoutSRV());
}
if (g_ibl) {
if (g_diffuseEnvironmentMap) {
g_pd3dDeviceContext->PSSetShaderResources(12, 1, &g_diffuseEnvironmentSRV);
}
if (g_specularEnvironmentMap) {
g_pd3dDeviceContext->PSSetShaderResources(13, 1, &g_specularEnvironmentSRV);
}
assert(g_iblSampler);
g_pd3dDeviceContext->PSSetSamplers(0, 1, &g_iblSampler);
}
}
//------------------------------------------------------------------------------
@ -1113,15 +1178,29 @@ display() {
// Clear the depth buffer.
g_pd3dDeviceContext->ClearDepthStencilView(g_pDepthStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0);
g_pd3dDeviceContext->OMSetDepthStencilState(g_pDepthStencilState, 1);
g_pd3dDeviceContext->RSSetState(g_pRasterizerState);
if (g_ibl && g_sky) {
// this query can be slow : turn off by default
//#define PIPELINE_STATISTICS
float modelView[16], projection[16], mvp[16];
double aspect = g_width/(double)g_height;
identity(modelView);
rotate(modelView, g_rotate[1], 1, 0, 0);
rotate(modelView, g_rotate[0], 0, 1, 0);
perspective(projection, 45.0f, (float)aspect, g_size*0.001f, g_size+g_dolly);
multMatrix(mvp, modelView, projection);
g_sky->Draw(g_pd3dDeviceContext, mvp);
}
// this query can be slow : comment out #define to turn off
#define PIPELINE_STATISTICS
#ifdef PIPELINE_STATISTICS
g_pd3dDeviceContext->Begin(g_pipelineStatsQuery);
#endif // PIPELINE_STATISTICS
g_pd3dDeviceContext->OMSetDepthStencilState(g_pDepthStencilState, 1);
g_pd3dDeviceContext->RSSetState(g_pRasterizerState);
drawModel();
#ifdef PIPELINE_STATISTICS
@ -1395,7 +1474,47 @@ initHUD() {
g_hud = new D3D11hud(g_pd3dDeviceContext);
g_hud->Init(g_width, g_height);
int compute_pulldown = g_hud->AddPullDown("Compute (K)", 475, 10, 300, callbackKernel, 'K');
if (g_osdPTexOcclusion != NULL) {
g_hud->AddCheckBox("Ambient Occlusion (A)", g_occlusion,
-200, 570, callbackCheckBox, HUD_CB_DISPLAY_OCCLUSION, 'a');
}
if (g_osdPTexSpecular != NULL)
g_hud->AddCheckBox("Specular (S)", g_specular,
-200, 590, callbackCheckBox, HUD_CB_DISPLAY_SPECULAR, 's');
if (g_diffuseEnvironmentMap || g_diffuseEnvironmentMap) {
g_hud->AddCheckBox("IBL (I)", g_ibl,
-200, 610, callbackCheckBox, HUD_CB_IBL, 'i');
}
g_hud->AddCheckBox("Animate vertices (M)", g_moveScale != 0.0,
10, 30, callbackCheckBox, HUD_CB_ANIMATE_VERTICES, 'm');
g_hud->AddCheckBox("Screen space LOD (V)", g_screenSpaceTess,
10, 50, callbackCheckBox, HUD_CB_VIEW_LOD, 'v');
g_hud->AddCheckBox("Fractional spacing (T)", g_fractionalSpacing,
10, 70, callbackCheckBox, HUD_CB_FRACTIONAL_SPACING, 't');
g_hud->AddCheckBox("Frustum Patch Culling (B)", g_patchCull,
10, 90, callbackCheckBox, HUD_CB_PATCH_CULL, 'b');
g_hud->AddCheckBox("Bloom (Y)", g_bloom,
10, 110, callbackCheckBox, HUD_CB_BLOOM, 'y');
g_hud->AddCheckBox("Freeze (spc)", g_freeze,
10, 130, callbackCheckBox, HUD_CB_FREEZE, ' ');
g_hud->AddRadioButton(HUD_RB_SCHEME, "CATMARK", true, 10, 190, callbackScheme, 0);
g_hud->AddRadioButton(HUD_RB_SCHEME, "BILINEAR", false, 10, 210, callbackScheme, 1);
g_hud->AddCheckBox("Adaptive (`)", g_adaptive,
10, 300, callbackCheckBox, HUD_CB_ADAPTIVE, '`');
for (int i = 1; i < 8; ++i) {
char level[16];
sprintf(level, "Lv. %d", i);
g_hud->AddRadioButton(HUD_RB_LEVEL, level, i == g_level,
10, 320+i*20, callbackLevel, i, '0'+i);
}
int compute_pulldown = g_hud->AddPullDown("Compute (K)", 475, 10, 300, callbackKernel, 'k');
g_hud->AddPullDownButton(compute_pulldown, "CPU (K)", kCPU);
#ifdef OPENSUBDIV_HAS_OPENMP
g_hud->AddPullDownButton(compute_pulldown, "OPENMP", kOPENMP);
@ -1413,32 +1532,6 @@ initHUD() {
#endif
g_hud->AddPullDownButton(compute_pulldown, "DirectCompute", kDirectCompute);
g_hud->AddCheckBox("Adaptive (`)", g_adaptive,
10, 300, callbackCheckBox, HUD_CB_ADAPTIVE, '`');
g_hud->AddCheckBox("Animate vertices (M)", g_moveScale != 0.0,
10, 30, callbackCheckBox, HUD_CB_ANIMATE_VERTICES, 'm');
g_hud->AddCheckBox("Screen space LOD (V)", g_screenSpaceTess,
10, 50, callbackCheckBox, HUD_CB_VIEW_LOD, 'v');
g_hud->AddCheckBox("Fractional spacing (T)", g_fractionalSpacing,
10, 70, callbackCheckBox, HUD_CB_FRACTIONAL_SPACING, 't');
g_hud->AddCheckBox("Frustum Patch Culling (B)", g_patchCull,
10, 90, callbackCheckBox, HUD_CB_PATCH_CULL, 'b');
g_hud->AddCheckBox("Bloom (Y)", g_bloom,
10, 110, callbackCheckBox, HUD_CB_BLOOM, 'y');
g_hud->AddCheckBox("Freeze (spc)", g_freeze,
10, 130, callbackCheckBox, HUD_CB_FREEZE, ' ');
g_hud->AddRadioButton(HUD_RB_SCHEME, "CATMARK", true, 10, 190, callbackScheme, 0, 's');
g_hud->AddRadioButton(HUD_RB_SCHEME, "BILINEAR", false, 10, 210, callbackScheme, 1, 's');
for (int i = 1; i < 8; ++i) {
char level[16];
sprintf(level, "Lv. %d", i);
g_hud->AddRadioButton(HUD_RB_LEVEL, level, i == g_level,
10, 320+i*20, callbackLevel, i, '0'+i);
}
int shading_pulldown = g_hud->AddPullDown("Shading (W)", 250, 10, 250, callbackWireframe, 'w');
g_hud->AddPullDownButton(shading_pulldown, "Wire", DISPLAY_WIRE, g_wire==DISPLAY_WIRE);
g_hud->AddPullDownButton(shading_pulldown, "Shaded", DISPLAY_SHADED, g_wire==DISPLAY_SHADED);
@ -1449,8 +1542,9 @@ initHUD() {
-200, 30, callbackColor, COLOR_NONE, 'c');
g_hud->AddRadioButton(HUD_RB_COLOR, "Ptex Nearest", (g_color == COLOR_PTEX_NEAREST),
-200, 50, callbackColor, COLOR_PTEX_NEAREST, 'c');
g_hud->AddRadioButton(HUD_RB_COLOR, "Ptex HW bilinear", (g_color == COLOR_PTEX_HW_BILINEAR),
-200, 70, callbackColor, COLOR_PTEX_HW_BILINEAR, 'c');
// Commented out : we need to add a texture sampler state to make this work
//g_hud->AddRadioButton(HUD_RB_COLOR, "Ptex HW bilinear", (g_color == COLOR_PTEX_HW_BILINEAR),
// -200, 70, callbackColor, COLOR_PTEX_HW_BILINEAR, 'c');
g_hud->AddRadioButton(HUD_RB_COLOR, "Ptex bilinear", (g_color == COLOR_PTEX_BILINEAR),
-200, 90, callbackColor, COLOR_PTEX_BILINEAR, 'c');
g_hud->AddRadioButton(HUD_RB_COLOR, "Ptex biquadratic", (g_color == COLOR_PTEX_BIQUADRATIC),
@ -1467,9 +1561,10 @@ initHUD() {
g_hud->AddRadioButton(HUD_RB_DISPLACEMENT, "None",
(g_displacement == DISPLACEMENT_NONE),
-200, 220, callbackDisplacement, DISPLACEMENT_NONE, 'd');
g_hud->AddRadioButton(HUD_RB_DISPLACEMENT, "HW bilinear",
(g_displacement == DISPLACEMENT_HW_BILINEAR),
-200, 240, callbackDisplacement, DISPLACEMENT_HW_BILINEAR, 'd');
// Commented out : we need to add a texture sampler state to make this work
//g_hud->AddRadioButton(HUD_RB_DISPLACEMENT, "HW bilinear",
// (g_displacement == DISPLACEMENT_HW_BILINEAR),
// -200, 240, callbackDisplacement, DISPLACEMENT_HW_BILINEAR, 'd');
g_hud->AddRadioButton(HUD_RB_DISPLACEMENT, "Bilinear",
(g_displacement == DISPLACEMENT_BILINEAR),
-200, 260, callbackDisplacement, DISPLACEMENT_BILINEAR, 'd');
@ -1505,14 +1600,6 @@ initHUD() {
g_hud->AddCheckBox("Seamless Mipmap", g_seamless,
-200, 530, callbackCheckBox, HUD_CB_SEAMLESS_MIPMAP, 'j');
if (g_osdPTexOcclusion != NULL) {
g_hud->AddCheckBox("Ambient Occlusion (A)", g_occlusion,
-200, 570, callbackCheckBox, HUD_CB_DISPLAY_OCCLUSION, 'a');
}
if (g_osdPTexSpecular != NULL)
g_hud->AddCheckBox("Specular (S)", g_specular,
-200, 590, callbackCheckBox, HUD_CB_DISPLAY_SPECULAR, 's');
}
//------------------------------------------------------------------------------
@ -1527,9 +1614,18 @@ initD3D11(HWND hWnd) {
UINT numDriverTypes = ARRAYSIZE(driverTypes);
int width = g_width,
height = g_height;
if (g_fullscreen) {
HWND const desktop = GetDesktopWindow();
RECT rect;
GetWindowRect(desktop, &rect);
width = (int)rect.right;
height = (int)rect.bottom;
}
DXGI_SWAP_CHAIN_DESC hDXGISwapChainDesc;
hDXGISwapChainDesc.BufferDesc.Width = g_width;
hDXGISwapChainDesc.BufferDesc.Height = g_height;
hDXGISwapChainDesc.BufferDesc.Width = width;
hDXGISwapChainDesc.BufferDesc.Height = height;
hDXGISwapChainDesc.BufferDesc.RefreshRate.Numerator = 0;
hDXGISwapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
hDXGISwapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
@ -1540,7 +1636,7 @@ initD3D11(HWND hWnd) {
hDXGISwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
hDXGISwapChainDesc.BufferCount = 1;
hDXGISwapChainDesc.OutputWindow = hWnd;
hDXGISwapChainDesc.Windowed = TRUE;
hDXGISwapChainDesc.Windowed = !g_fullscreen;
hDXGISwapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
hDXGISwapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
@ -1806,6 +1902,23 @@ tokenize(std::string const & src) {
return result;
}
//------------------------------------------------------------------------------
void usage(const char *program) {
printf("Usage: %s [options] <color.ptx> [<displacement.ptx>] [occlusion.ptx>] "
"[specular.ptx] [pose.obj]...\n", program);
printf("Options: -l level : subdivision level\n");
printf(" -c count : frame count until exit (for profiler)\n");
printf(" -d <diffseEnvMap.hdr> : diffuse environment map for IBL\n");
printf(" -e <specularEnvMap.hdr> : specular environment map for IBL\n");
printf(" -s <shaderfile.glsl> : custom shader file\n");
printf(" -y : Y-up model\n");
printf(" -m level : max mimmap level (default=10)\n");
printf(" -x <ptex limit MB> : ptex target memory size\n");
printf(" --disp <scale> : Displacment scale\n");
}
//------------------------------------------------------------------------------
int WINAPI
WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) {
@ -1860,6 +1973,8 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmd
diffuseEnvironmentMap = argv[++i].c_str();
else if (argv[i] == "-e")
specularEnvironmentMap = argv[++i].c_str();
else if (argv[i] == "-f")
g_fullscreen = true;
else if (argv[i] == "-y")
g_yup = true;
else if (argv[i] == "-m")
@ -1887,7 +2002,7 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmd
g_ptexColorFilename = colorFilename;
if (g_ptexColorFilename == NULL) {
printf("Usage: \n");
usage(argv[0].c_str());
return 1;
}
@ -1938,6 +2053,57 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmd
printf("\n");
}
// IBL textures
if (diffuseEnvironmentMap) {
g_diffuseEnvironmentMap =
createHDRTexture(g_pd3dDevice, diffuseEnvironmentMap);
assert(g_diffuseEnvironmentMap);
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
ZeroMemory(&srvDesc, sizeof(srvDesc));
srvDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
srvDesc.Texture2D.MostDetailedMip = 0;
srvDesc.Texture2D.MipLevels = 1;
g_pd3dDevice->CreateShaderResourceView(g_diffuseEnvironmentMap, &srvDesc, &g_diffuseEnvironmentSRV);
assert(g_diffuseEnvironmentSRV);
}
if (specularEnvironmentMap) {
g_specularEnvironmentMap =
createHDRTexture(g_pd3dDevice, specularEnvironmentMap);
assert(g_specularEnvironmentMap);
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
ZeroMemory(&srvDesc, sizeof(srvDesc));
srvDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
srvDesc.Texture2D.MostDetailedMip = 0;
srvDesc.Texture2D.MipLevels = 1;
g_pd3dDevice->CreateShaderResourceView(g_specularEnvironmentMap, &srvDesc, &g_specularEnvironmentSRV);
assert(g_specularEnvironmentSRV);
}
if (g_diffuseEnvironmentMap || g_specularEnvironmentMap) {
// texture sampler
D3D11_SAMPLER_DESC samplerDesc;
ZeroMemory(&samplerDesc, sizeof(samplerDesc));
samplerDesc.Filter = D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT;
samplerDesc.AddressU = samplerDesc.AddressV = samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
samplerDesc.MaxAnisotropy = 0;
samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
samplerDesc.MinLOD = 0;
samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
samplerDesc.BorderColor[0] = samplerDesc.BorderColor[1] = samplerDesc.BorderColor[2] = samplerDesc.BorderColor[3] = 0.0f;
g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_iblSampler);
g_sky = new Sky(g_pd3dDevice, g_specularEnvironmentMap!=0 ?
g_specularEnvironmentMap : g_diffuseEnvironmentMap);
}
initHUD();
fitFrame();

View File

@ -30,6 +30,7 @@ cbuffer Transform : register( b0 ) {
float4x4 ModelViewMatrix;
float4x4 ProjectionMatrix;
float4x4 ModelViewProjectionMatrix;
float4x4 ModelViewInverseMatrix;
};
cbuffer Tessellation : register( b1 ) {
@ -289,6 +290,31 @@ void gs_main( triangle OutputVertex input[3],
#endif
// ---------------------------------------------------------------------------
// IBL lighting
// ---------------------------------------------------------------------------
Texture2D diffuseEnvironmentMap : register(t12);
Texture2D specularEnvironmentMap : register(t13);
SamplerState iblSampler : register(s0);
#define M_PI 3.14159265358
float4
gamma(float4 value, float g) {
return float4(pow(value.xyz, float3(g,g,g)), 1);
}
float4
getEnvironmentHDR(Texture2D tx, SamplerState sm, float3 dir)
{
dir = mul(ModelViewInverseMatrix, float4(dir, 0)).xyz;
float2 uv = float2((atan2(dir.x,dir.z)/M_PI+1)*0.5, (1-dir.y)*0.5);
return tx.Sample(sm, uv);
}
// ---------------------------------------------------------------------------
// Lighting
// ---------------------------------------------------------------------------
@ -559,8 +585,38 @@ ps_main(in OutputVertex input,
#else
float specular = 1.0;
#endif
// ------------ lighting ---------------
#ifdef USE_IBL
// non-plausible BRDF
float4 a = float4(0, 0, 0, 1); //ambientColor;
float4 d = getEnvironmentHDR(diffuseEnvironmentMap, iblSampler, normal);
float3 eye = normalize(input.position.xyz - float3(0,0,0));
float3 r = reflect(eye, normal);
float4 s = getEnvironmentHDR(specularEnvironmentMap, iblSampler, r);
const float fresnelBias = 0.01;
const float fresnelScale = 1.0;
const float fresnelPower = 3.5;
float F = fresnelBias + fresnelScale * pow(1.0+dot(normal,eye), fresnelPower);
// Geometric attenuation term (
float NoV = dot(normal, -eye);
float alpha = 0.75 * 0.75; // roughness ^ 2
float k = alpha * 0.5;
float G = NoV/(NoV*(1-k)+k);
a *= (1-occ);
d *= (1-occ);
s *= min(specular, (1-occ)) * (F*G);
float4 Cf = (a+d)*texColor*(1-F)/M_PI + s;
//Cf = gamma(Cf, 2.2);
#else
float4 Cf = lighting(texColor, input.position.xyz, normal, occ);
#endif
// ------------ wireframe ---------------
outColor = edgeColor(Cf, input.edgeDistance);

View File

@ -0,0 +1,257 @@
//
// Copyright 2013 Nvidia
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#include "./sky.h"
#include "../common/d3d11Utils.h"
#include <cassert>
#include <vector>
static const char *g_skyShaderSource =
#include "skyshader.gen.h"
;
#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
// shader constants
__declspec(align(16)) struct CB_CONSTANTS {
float ModelViewMatrix[16];
};
Sky::Sky(ID3D11Device * device, ID3D11Texture2D * environmentMap) :
numIndices(0),
vertexShader(0),
pixelShader(0),
shaderConstants(0),
texture(environmentMap), // we do not own this - we do not release it !
textureSRV(0),
textureSS(0),
inputLayout(0),
rasterizerState(0),
depthStencilState(0),
sphere(0),
sphereIndices(0) {
initialize(device);
}
Sky::~Sky() {
SAFE_RELEASE(vertexShader);
SAFE_RELEASE(pixelShader);
SAFE_RELEASE(shaderConstants);
SAFE_RELEASE(inputLayout);
SAFE_RELEASE(rasterizerState);
SAFE_RELEASE(depthStencilState);
SAFE_RELEASE(textureSS);
SAFE_RELEASE(textureSRV);
SAFE_RELEASE(sphere);
SAFE_RELEASE(sphereIndices);
}
void
Sky::initialize(ID3D11Device * device) {
// compile shaders
ID3DBlob * pVSBlob = D3D11Utils::CompileShader(g_skyShaderSource, "vs_main", "vs_5_0"),
* pPSBlob = D3D11Utils::CompileShader(g_skyShaderSource, "ps_main", "ps_5_0");
assert(pVSBlob && pPSBlob);
device->CreateVertexShader(pVSBlob->GetBufferPointer(),
pVSBlob->GetBufferSize(), NULL, &vertexShader);
assert(vertexShader);
device->CreatePixelShader(pPSBlob->GetBufferPointer(),
pPSBlob->GetBufferSize(), NULL, &pixelShader);
assert(pixelShader);
// VBO layout
D3D11_INPUT_ELEMENT_DESC inputElementDesc[] = {
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, sizeof(float)*3, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
device->CreateInputLayout(inputElementDesc, ARRAYSIZE(inputElementDesc),
pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), &inputLayout);
assert(inputLayout);
// shader constants
D3D11_BUFFER_DESC cbDesc;
ZeroMemory(&cbDesc, sizeof(cbDesc));
cbDesc.Usage = D3D11_USAGE_DYNAMIC;
cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
cbDesc.MiscFlags = 0;
cbDesc.ByteWidth = sizeof(CB_CONSTANTS);
device->CreateBuffer(&cbDesc, NULL, &shaderConstants);
assert(shaderConstants);
// texture SRV
assert(texture);
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
ZeroMemory(&srvDesc, sizeof(srvDesc));
srvDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
srvDesc.Texture2D.MostDetailedMip = 0;
srvDesc.Texture2D.MipLevels = 1;
device->CreateShaderResourceView(texture, &srvDesc, &textureSRV);
assert(textureSRV);
// texture sampler
D3D11_SAMPLER_DESC samplerDesc;
ZeroMemory(&samplerDesc, sizeof(samplerDesc));
samplerDesc.Filter = D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT;
samplerDesc.AddressU = samplerDesc.AddressV = samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
samplerDesc.MaxAnisotropy = 0;
samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
samplerDesc.MinLOD = 0;
samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
samplerDesc.BorderColor[0] = samplerDesc.BorderColor[1] = samplerDesc.BorderColor[2] = samplerDesc.BorderColor[3] = 0.0f;
device->CreateSamplerState(&samplerDesc, &textureSS);
// depth stencil state
D3D11_DEPTH_STENCIL_DESC depthStencilDesc;
ZeroMemory(&depthStencilDesc, sizeof(depthStencilDesc));
depthStencilDesc.DepthEnable = true;
depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO;
depthStencilDesc.DepthFunc = D3D11_COMPARISON_LESS_EQUAL;
depthStencilDesc.StencilEnable = false;
device->CreateDepthStencilState(&depthStencilDesc, &depthStencilState);
// rasterizer state
D3D11_RASTERIZER_DESC rasDesc;
rasDesc.FillMode = D3D11_FILL_SOLID;
rasDesc.CullMode = D3D11_CULL_NONE;
rasDesc.FrontCounterClockwise = FALSE;
rasDesc.DepthBias = 0;
rasDesc.DepthBiasClamp = 0;
rasDesc.DepthClipEnable = FALSE;
rasDesc.SlopeScaledDepthBias = 0.0f;
rasDesc.ScissorEnable = FALSE;
rasDesc.MultisampleEnable = FALSE;
rasDesc.AntialiasedLineEnable = FALSE;
device->CreateRasterizerState(&rasDesc, &rasterizerState);
assert(rasterizerState);
const int U_DIV = 20,
V_DIV = 20;
std::vector<float> vbo;
std::vector<int> indices;
for (int u = 0; u <= U_DIV; ++u) {
for (int v = 0; v < V_DIV; ++v) {
float s = float(2*M_PI*float(u)/U_DIV);
float t = float(M_PI*float(v)/(V_DIV-1));
vbo.push_back(-sin(t)*sin(s));
vbo.push_back(cos(t));
vbo.push_back(-sin(t)*cos(s));
vbo.push_back(u/float(U_DIV));
vbo.push_back(v/float(V_DIV));
if (v > 0 && u > 0) {
indices.push_back((u-1)*V_DIV+v-1);
indices.push_back(u*V_DIV+v-1);
indices.push_back((u-1)*V_DIV+v);
indices.push_back((u-1)*V_DIV+v);
indices.push_back(u*V_DIV+v-1);
indices.push_back(u*V_DIV+v);
}
}
}
D3D11_BUFFER_DESC bufferDesc;
D3D11_SUBRESOURCE_DATA subData;
// topology indices
ZeroMemory(&bufferDesc, sizeof(bufferDesc));
bufferDesc.ByteWidth = (int)indices.size() * sizeof(int);
bufferDesc.Usage = D3D11_USAGE_DEFAULT;
bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
bufferDesc.CPUAccessFlags = 0;
bufferDesc.MiscFlags = 0;
bufferDesc.StructureByteStride = sizeof(int);
ZeroMemory(&subData, sizeof(subData));
subData.pSysMem = &indices[0];
subData.SysMemPitch = 0;
subData.SysMemSlicePitch = 0;
device->CreateBuffer(&bufferDesc, &subData, &sphereIndices);
assert(sphereIndices);
// VBO
ZeroMemory(&bufferDesc, sizeof(bufferDesc));
bufferDesc.ByteWidth = (int)vbo.size() * sizeof(float);
bufferDesc.Usage = D3D11_USAGE_DEFAULT;
bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bufferDesc.CPUAccessFlags = 0;
bufferDesc.MiscFlags = 0;
ZeroMemory(&subData, sizeof(subData));
subData.pSysMem = &vbo[0];
device->CreateBuffer(&bufferDesc, &subData, &sphere);
assert(sphere);
numIndices = (int)indices.size();
}
void
Sky::Draw(ID3D11DeviceContext * deviceContext, float const mvp[16]) {
if (vertexShader==0 || pixelShader==0 || shaderConstants==0) return;
if (texture==0 || textureSRV==0 || textureSS==0) return;
if (sphere==0 || sphereIndices==0) return;
// update shader constants
D3D11_MAPPED_SUBRESOURCE MappedResource;
deviceContext->Map(shaderConstants, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource);
CB_CONSTANTS* pData = (CB_CONSTANTS*)MappedResource.pData;
memcpy(pData->ModelViewMatrix, mvp, 16*sizeof(float));
deviceContext->Unmap(shaderConstants, 0);
// draw
deviceContext->RSSetState(rasterizerState);
deviceContext->OMSetDepthStencilState(depthStencilState, 1);
deviceContext->VSSetShader(vertexShader, NULL, 0);
deviceContext->VSSetConstantBuffers(0, 1, &shaderConstants);
deviceContext->PSSetShader(pixelShader, NULL, 0);
deviceContext->PSSetShaderResources(0, 1, &textureSRV);
deviceContext->PSSetSamplers(0, 1, &textureSS);
UINT hStrides = 5*sizeof(float);
UINT hOffsets = 0;
deviceContext->IASetVertexBuffers(0, 1, &sphere, &hStrides, &hOffsets);
deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
deviceContext->IASetInputLayout(inputLayout);
deviceContext->IASetIndexBuffer(sphereIndices, DXGI_FORMAT_R32_UINT, 0);
deviceContext->DrawIndexed(numIndices, 0, 0);
}

View File

@ -0,0 +1,65 @@
//
// Copyright 2013 Nvidia
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#include <D3D11.h>
#include <D3Dcompiler.h>
//
// Draws an environment sphere centered on the camera w/ a texture
//
class Sky {
public:
// Constructor (Sky does not own the texture asset)
Sky(ID3D11Device * device, ID3D11Texture2D * environmentMap);
~Sky();
void Draw(ID3D11DeviceContext * deviceContext, float const mvp[16]);
private:
void initialize(ID3D11Device * device);
private:
int numIndices;
ID3D11VertexShader * vertexShader;
ID3D11PixelShader * pixelShader;
ID3D11Buffer * shaderConstants;
ID3D11InputLayout * inputLayout;
ID3D11RasterizerState * rasterizerState;
ID3D11DepthStencilState * depthStencilState;
ID3D11Texture2D * texture;
ID3D11ShaderResourceView * textureSRV;
ID3D11SamplerState * textureSS;
ID3D11Buffer * sphere;
ID3D11Buffer * sphereIndices;
};

View File

@ -0,0 +1,80 @@
//
// Copyright 2013 Nvidia
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
struct VS_InputVertex {
float3 position : POSITION0;
float2 texCoord : TEXCOORD0;
};
struct VS_OutputVertex {
float4 position : SV_POSITION0;
float2 texCoord : TEXCOORD0;
};
cbuffer Transform : register( b0 ) {
float4x4 ModelViewMatrix;
};
//--------------------------------------------------------------
// sky vertex shader
//--------------------------------------------------------------
void vs_main(in VS_InputVertex input,
out VS_OutputVertex output) {
output.position = mul(ModelViewMatrix, float4(input.position,1));
output.texCoord = input.texCoord;
}
//--------------------------------------------------------------
// sky pixel shader
//--------------------------------------------------------------
struct PS_InputVertex {
float4 position : SV_POSITION0;
float2 texCoord : TEXCOORD0;
};
Texture2D tx : register(t0);
SamplerState sm : register(s0);
float4
gamma(float4 value, float g) {
return float4(pow(value.xyz, float3(g,g,g)), 1);
}
float4
ps_main(in PS_InputVertex input) : SV_Target {
float4 tex = tx.Sample(sm, input.texCoord.xy);
//float4 outColor = gamma(tex,0.4545);
float4 outColor = tex;
return outColor;
}