graphics

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

commit 448d23695c37d1b945e060800369ab5e36722837
parent a3fc00fe95cb001f97224e892f45bcf731484143
Author: Brian Swetland <swetland@frotz.net>
Date:   Mon,  4 Feb 2013 00:33:13 -0800

textgrid class for drawing simple text overlays

Diffstat:
Mcommon/app.h | 47++++++++++++++++++++++++++++++-----------------
Mcommon/dxapp.cc | 25+++++++++++++++++++++----
Mcommon/matrix.cc | 8++++----
Ahello/TextPS.hlsl | 13+++++++++++++
Ahello/TextVS.hlsl | 41+++++++++++++++++++++++++++++++++++++++++
Mhello/hello.vcxproj | 13++++++++++++-
Ahello/textgrid.cc | 131+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ahello/textgrid.h | 47+++++++++++++++++++++++++++++++++++++++++++++++
8 files changed, 299 insertions(+), 26 deletions(-)

diff --git a/common/app.h b/common/app.h @@ -48,6 +48,27 @@ public: int reconfigure(int init); void setActive(int a) { active = a; }; void setMouseXY(int x, int y) { mouseWX = x; mouseWY = y; }; + + int createTextureRGBA(void *data, int tw, int th, + int genmips, ID3D10ShaderResourceView **srv); + int createBuffer(D3D10_BIND_FLAG flag, + void *data, int sz, ID3D10Buffer **buf); + void updateBuffer(ID3D10Buffer *buf, void *data) { + device->UpdateSubresource(buf, 0, NULL, data, 0, 0); + } + + int createVtxBuffer(void *data, int sz, ID3D10Buffer **buf) { + return createBuffer(D3D10_BIND_VERTEX_BUFFER, data, sz, buf); + } + int createIdxBuffer(void *data, int sz, ID3D10Buffer **buf) { + return createBuffer(D3D10_BIND_INDEX_BUFFER, data, sz, buf); + } + int createConstantBuffer(int sz, ID3D10Buffer **buf) { + return createBuffer(D3D10_BIND_CONSTANT_BUFFER, NULL, sz, buf); + } + int compileVertexShader(const char *fn, ID3D10VertexShader **vs, ID3D10Blob **data); + int compilePixelShader(const char *fn, ID3D10PixelShader **ps, ID3D10Blob **data); + protected: int width; int height; @@ -66,23 +87,9 @@ protected: ID3D10RenderTargetView *targetView; ID3D10Texture2D *depthBuffer; ID3D10DepthStencilView *depthView; - ID3D10RasterizerState *rasterizerState; - - int createTextureRGBA(void *data, int tw, int th, - int genmips, ID3D10ShaderResourceView **srv); - int createBuffer(D3D10_BIND_FLAG flag, - void *data, int sz, ID3D10Buffer **buf); - int createVtxBuffer(void *data, int sz, ID3D10Buffer **buf) { - return createBuffer(D3D10_BIND_VERTEX_BUFFER, data, sz, buf); - } - int createIdxBuffer(void *data, int sz, ID3D10Buffer **buf) { - return createBuffer(D3D10_BIND_INDEX_BUFFER, data, sz, buf); - } - int createConstantBuffer(int sz, ID3D10Buffer **buf) { - return createBuffer(D3D10_BIND_CONSTANT_BUFFER, NULL, sz, buf); - } - int compileVertexShader(const char *fn, ID3D10VertexShader **vs, ID3D10Blob **data); - int compilePixelShader(const char *fn, ID3D10PixelShader **ps, ID3D10Blob **data); + ID3D10RasterizerState *rsDefault; + ID3D10DepthStencilState *dsDepthEnabled; + ID3D10DepthStencilState *dsDepthDisabled; private: LPDIRECTINPUT8 dinput; @@ -95,6 +102,12 @@ private: int active; }; +struct Texture2D { + ID3D10Texture2D *tex; + ID3D10ShaderResourceView *srv; + Texture2D() : tex(NULL), srv(NULL) {}; +}; + int compileShader(const char *fn, const char *profile, ID3D10Blob **shader); App *createApp(void); diff --git a/common/dxapp.cc b/common/dxapp.cc @@ -24,7 +24,7 @@ LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); App::App() : width(800), height(600), active(0), mouseDX(0), mouseDY(0), mouseDZ(0), mouseBTN(0), device(NULL), targetView(NULL), depthView(NULL), - swapchain(NULL), rasterizerState(NULL) { + swapchain(NULL), rsDefault(NULL), dsDepthEnabled(NULL), dsDepthDisabled(NULL) { } App::~App() { @@ -40,7 +40,9 @@ void App::stop(void) { release(); - if (rasterizerState) rasterizerState->Release(); + if (rsDefault) rsDefault->Release(); + if (dsDepthEnabled) dsDepthEnabled->Release(); + if (dsDepthDisabled) dsDepthDisabled->Release(); if (depthView) depthView->Release(); if (depthBuffer) depthBuffer->Release(); if (targetView) targetView->Release(); @@ -347,11 +349,26 @@ int App::initD3D(void) { rd.ScissorEnable = false; rd.MultisampleEnable = false; rd.AntialiasedLineEnable = false; - hr = device->CreateRasterizerState(&rd, &rasterizerState); + hr = device->CreateRasterizerState(&rd, &rsDefault); if (FAILED(hr)) return -1; - device->RSSetState(rasterizerState); + D3D10_DEPTH_STENCIL_DESC dsd; + memset(&dsd, 0, sizeof(dsd)); + dsd.DepthEnable = true; + dsd.DepthWriteMask = D3D10_DEPTH_WRITE_MASK_ALL; + dsd.DepthFunc = D3D10_COMPARISON_LESS; + dsd.StencilEnable = false; + dsd.StencilReadMask = D3D10_DEFAULT_STENCIL_READ_MASK; + dsd.StencilWriteMask = D3D10_DEFAULT_STENCIL_WRITE_MASK; + hr = device->CreateDepthStencilState(&dsd, &dsDepthEnabled); + if (FAILED(hr)) + return -1; + hr = device->CreateDepthStencilState(&dsd, &dsDepthDisabled); + if (FAILED(hr)) + return -1; + + device->RSSetState(rsDefault); return S_OK; } diff --git a/common/matrix.cc b/common/matrix.cc @@ -114,10 +114,10 @@ void __mat4_set_ortho(float m[16], float l, float r, float b, float t, float n, memset(m, 0, sizeof(float[16])); m[0] = 2.0 / (r - l); m[5] = 2.0 / (t - b); - m[10] = -2.0 / (f - n); - m[12] = -((r + l) / (r - l)); - m[13] = -((t + b) / (t - b)); - m[14] = -((f + n) / (f - n)); + m[10] = 1.0 / (n - f); + m[12] = (l + r) / (l - r); + m[13] = (t + b) / (b - t); + m[14] = n / (n - f); m[15] = 1.0; } diff --git a/hello/TextPS.hlsl b/hello/TextPS.hlsl @@ -0,0 +1,13 @@ + +Texture2D Texture0; + +SamplerState samLinear; + +struct VS_OUTPUT { + float4 Position : SV_POSITION; + float2 TexCoord : TEXCOORD; +}; + +float4 main(VS_OUTPUT input) : SV_Target { + return Texture0.Sample(samLinear, input.TexCoord); +} diff --git a/hello/TextVS.hlsl b/hello/TextVS.hlsl @@ -0,0 +1,41 @@ + +cbuffer cb0 { + matrix MVP; + unsigned int cw; + unsigned int ch; +}; +struct VS_OUTPUT { + float4 Position : SV_POSITION; + float2 TexCoord : TEXCOORD; +}; + +VS_OUTPUT main( + float4 pos : POSITION, + float2 uv : TEXCOORD, + unsigned int c : CHARACTER, + unsigned int id : SV_INSTANCEID + ) { + + VS_OUTPUT output = (VS_OUTPUT) 0; + + // shift unit rectangle to character cell rectangle + pos.xy += float2(id % cw, (ch-1) - id / ch); + + // adjust unit texture coord to font cell rectangle + float tx = (c % 16); + float ty = (15 - c / 16); + + output.Position = mul(MVP, pos); + output.TexCoord = + // scale to size of character in fonttexture + uv * float2(1.0/16.0,1.0/16.0) + // move to correct character + + float2(tx/16.0,ty/16.0) + // offset to avoid cruft + + float2(1.0/256.0,-1.0/256.0); + + // discard via clipping + if (c == 0) output.Position.z = -1.1; + + return output; +} diff --git a/hello/hello.vcxproj b/hello/hello.vcxproj @@ -89,11 +89,13 @@ <ClCompile Include="..\common\savepng.cc" /> <ClCompile Include="..\common\simplexnoise.cc" /> <ClCompile Include="hello.cc" /> + <ClCompile Include="textgrid.cc" /> </ItemGroup> <ItemGroup> <ClInclude Include="..\common\app.h" /> <ClInclude Include="..\common\matrix.h" /> <ClInclude Include="..\common\util.h" /> + <ClInclude Include="textgrid.h" /> </ItemGroup> <ItemGroup> <FxCompile Include="SimplePS.hlsl"> @@ -102,6 +104,14 @@ <ShaderModel Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">4.0</ShaderModel> <ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Pixel</ShaderType> </FxCompile> + <FxCompile Include="TextPS.hlsl"> + <ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Pixel</ShaderType> + <ShaderModel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">4.0</ShaderModel> + </FxCompile> + <FxCompile Include="TextVS.hlsl"> + <ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Vertex</ShaderType> + <ShaderModel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">4.0</ShaderModel> + </FxCompile> </ItemGroup> <ItemGroup> <FxCompile Include="SimpleVS.hlsl"> @@ -113,4 +123,4 @@ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <ImportGroup Label="ExtensionTargets"> </ImportGroup> -</Project> +</Project> +\ No newline at end of file diff --git a/hello/textgrid.cc b/hello/textgrid.cc @@ -0,0 +1,130 @@ +/* Copyright 2013 Brian Swetland <swetland@frotz.net> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> + +#include "app.h" +#include "util.h" +#include "matrix.h" +#include "textgrid.h" + +static D3D10_INPUT_ELEMENT_DESC text_layout_desc[] = { + { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 }, + { "CHARACTER", 0, DXGI_FORMAT_R8_UINT, 1, 0, D3D10_INPUT_PER_INSTANCE_DATA, 1 }, +}; + +static float unit_box_2d[] = { + 0, 1, 0, 1, + 0, 0, 0, 0, + 1, 0, 1, 0, + 1, 0, 1, 0, + 1, 1, 1, 1, + 0, 1, 0, 1, +}; + +int TextGrid::init(App *a, ID3D10Device *device, int w, int h) { + void *data; + unsigned int dw, dh; + HRESULT hr; + + struct { + mat4 proj; + unsigned cw; + unsigned ch; + unsigned pad0; + unsigned pad1; + } cb; + + width = w; + height = h; + dirty = 0; + + grid = (unsigned char*) malloc(w * h); + if (!grid) + return -1; + clear(); + + ID3D10Blob *blob; + if (!(data = load_png_rgba("font-vincent-8x8.png", &dw, &dh, 1))) + return error("cannot load texture"); + if (a->createTextureRGBA(data, dw, dh, 0, &texture)) + return -1; + free(data); + + if (a->createVtxBuffer(unit_box_2d, sizeof(unit_box_2d), &vtxbuf)) + return -1; + if (a->createVtxBuffer(grid, width * height, &charbuf)) + return -1; + if (a->compilePixelShader("TextPS.hlsl", &PS, NULL)) + return -1; + if (a->compileVertexShader("TextVS.hlsl", &VS, &blob)) + return -1; + if (a->createConstantBuffer(sizeof(cb), &cbuf)) + return -1; + + cb.proj.setOrtho(0, w, 0, h, -1, 1); + cb.cw = width; + cb.ch = height; + a->updateBuffer(cbuf, &cb); + + hr = device->CreateInputLayout(text_layout_desc, + sizeof(text_layout_desc) / sizeof(text_layout_desc[0]), + blob->GetBufferPointer(), blob->GetBufferSize(), &layout); + blob->Release(); + if (FAILED(hr)) + return -1; + stride[0] = 16; + stride[1] = 1; + offset[0] = 0; + offset[1] = 0; + buffer[0] = vtxbuf; + buffer[1] = charbuf; + return 0; +} + +void TextGrid::render(App *a, ID3D10Device *device) { + if (dirty) { + dirty = 0; + a->updateBuffer(charbuf, grid); + } + device->VSSetShader(VS); + device->PSSetShader(PS); + device->VSSetConstantBuffers(0, 1, &cbuf); + device->PSSetShaderResources(0, 1, &texture); + device->IASetInputLayout(layout); + device->IASetVertexBuffers(0, 2, buffer, stride, offset); + device->DrawInstanced(6, width * height, 0, 0); +} + +void TextGrid::clear(void) { + memset(grid, 0, width * height); +} + +void TextGrid::printf(int x, int y, const char *fmt, ...) { + char buf[128]; + int len; + va_list ap; + va_start(ap, fmt); + len = vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + buf[127] = 0; + if (len > 127) len = 127; + if (y < 0) y = height + y; + memcpy(grid + y * width + x, buf, len); // TODO rangecheck + dirty = 1; +} +\ No newline at end of file diff --git a/hello/textgrid.h b/hello/textgrid.h @@ -0,0 +1,46 @@ +/* Copyright 2013 Brian Swetland <swetland@frotz.net> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _TEXTGRID_H_ +#define _TEXTGRID_H_ + +class TextGrid { +public: + int init(App *a, ID3D10Device *device, int w, int h); + void render(App *a, ID3D10Device *device); + void clear(void); + void printf(int x, int y, const char *fmt, ...); + +private: + int width; + int height; + int dirty; + + ID3D10InputLayout *layout; + ID3D10Buffer *vtxbuf; + ID3D10Buffer *charbuf; + ID3D10PixelShader *PS; + ID3D10VertexShader *VS; + ID3D10ShaderResourceView *texture; + ID3D10Buffer *cbuf; + + unsigned char *grid; + + UINT stride[2]; + UINT offset[2]; + ID3D10Buffer *buffer[2]; +}; + +#endif +\ No newline at end of file