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:
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