*
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
Demo_TexturedTriangle/Debug/
|
||||
*.filters
|
||||
*.user
|
||||
Debug/
|
||||
*.suo
|
||||
*.db
|
||||
*.opendb
|
||||
*.plog
|
||||
Demo_TexturedTriangle/Release/Demo_Tex.C6A5DFA2.tlog/CL.command.1.tlog
|
||||
Demo_TexturedTriangle/Release/
|
||||
SoftGL/Release/
|
||||
Release/
|
||||
SoftGL/BlockRasterizer.i-58160ea9
|
||||
SoftGL/BlockRasterizer.i-f3af7022
|
||||
/build
|
||||
Vendored
+84
@@ -0,0 +1,84 @@
|
||||
|
||||
|
||||
add_library(SoftGL INTERFACE)
|
||||
|
||||
target_include_directories(SoftGL
|
||||
INTERFACE
|
||||
Src
|
||||
)
|
||||
|
||||
target_link_libraries(SoftGL
|
||||
INTERFACE
|
||||
LMath
|
||||
)
|
||||
|
||||
target_sources(SoftGL
|
||||
INTERFACE
|
||||
Src/SoftGL/Bitmap.h
|
||||
Src/SoftGL/BlockRasterizer.h
|
||||
Src/SoftGL/Buffer.h
|
||||
Src/SoftGL/config.h
|
||||
Src/SoftGL/Debug.h
|
||||
Src/SoftGL/DisplayMode.h
|
||||
Src/SoftGL/dynamic_buffer.h
|
||||
Src/SoftGL/Engine/FpsCounter.h
|
||||
Src/SoftGL/Graphics2D.h
|
||||
Src/SoftGL/IndexBuffer.h
|
||||
Src/SoftGL/InputLayout.h
|
||||
Src/SoftGL/InputSystem.h
|
||||
Src/SoftGL/IRenderWindow.h
|
||||
Src/SoftGL/IShader.h
|
||||
Src/SoftGL/LString.h
|
||||
Src/SoftGL/mip_utils.h
|
||||
Src/SoftGL/PixelShader.h
|
||||
Src/SoftGL/PSDefault.h
|
||||
Src/SoftGL/PSDefaultColor.h
|
||||
Src/SoftGL/PSFont.h
|
||||
Src/SoftGL/PSTextured.h
|
||||
Src/SoftGL/RasterizerSettings.h
|
||||
Src/SoftGL/Ray.h
|
||||
Src/SoftGL/RegisterBlock.h
|
||||
Src/SoftGL/ResourceManager.h
|
||||
Src/SoftGL/StaticBuffer.h
|
||||
Src/SoftGL/StaticTexture.h
|
||||
Src/SoftGL/static_mip_chain.h
|
||||
Src/SoftGL/static_vector.h
|
||||
Src/SoftGL/Texture.h
|
||||
Src/SoftGL/TextureSampler.h
|
||||
Src/SoftGL/texture_utils.h
|
||||
Src/SoftGL/Tools.h
|
||||
Src/SoftGL/Vertex.h
|
||||
Src/SoftGL/VertexShader.h
|
||||
Src/SoftGL/Viewport.h
|
||||
Src/SoftGL/VSDefault.h
|
||||
Src/SoftGL/VSScreenSpace.h
|
||||
|
||||
|
||||
Src/SoftGL/Engine/camera.h
|
||||
Src/SoftGL/Engine/camera_controller.h
|
||||
Src/SoftGL/Engine/cube_generator.h
|
||||
Src/SoftGL/Engine/FpsCounter.h
|
||||
Src/SoftGL/Engine/fresnel.h
|
||||
Src/SoftGL/Engine/gameobject.h
|
||||
Src/SoftGL/Engine/imesh.h
|
||||
Src/SoftGL/Engine/mesh.h
|
||||
Src/SoftGL/Engine/plane_generator.h
|
||||
Src/SoftGL/Engine/PsNormalMap.h
|
||||
Src/SoftGL/Engine/transform.h
|
||||
Src/SoftGL/Engine/shaders/textured_no_lit.h
|
||||
|
||||
|
||||
Src/SoftGL/ImageDataAccessorR5G6B5.h
|
||||
Src/SoftGL/ImageDataAccessorR8G8B8.h
|
||||
INTERFACE
|
||||
Src/SoftGL/BlockRasterizer.cpp
|
||||
|
||||
)
|
||||
|
||||
|
||||
if (WIN32)
|
||||
target_sources(SoftGL
|
||||
INTERFACE
|
||||
Src/SoftGL/Platform/Windows/RenderWindow.cpp
|
||||
)
|
||||
endif (WIN32)
|
||||
Vendored
+21
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 Sergey Serb
|
||||
|
||||
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.
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
# softgl
|
||||
C++ Software 3D renderer
|
||||
@@ -0,0 +1,88 @@
|
||||
#ifndef lighting_core_h__
|
||||
#define lighting_core_h__
|
||||
|
||||
#include <LMath/lmath.h>
|
||||
#include <algorithm>
|
||||
|
||||
#ifndef MATH_PI
|
||||
#define MATH_PI 3.1415926535
|
||||
#endif
|
||||
|
||||
using namespace lm;
|
||||
|
||||
float FresnelSchlickDielectric(float ior, float3 l, float3 h) {
|
||||
float f0 = std::pow((1.0f - ior) / (1.0f + ior), 2.0f);
|
||||
return f0 + (1.0f - f0) * std::pow(1.0f - dot(l, h), 5.0f);
|
||||
}
|
||||
|
||||
float FresnelSchlickConductor(float ior, float absorbtion, float3 l, float3 h) {
|
||||
float n = ior;
|
||||
float k = absorbtion;
|
||||
return (std::pow(n - 1, 2) + 4.0f * n*std::pow(1.0f - dot(l, h), 5.0f) + k*k) / (std::pow(n + 1.0f, 2.0f) + k*k);
|
||||
}
|
||||
|
||||
float G_implicit(float3 n, float3 h, float3 v, float3 l) {
|
||||
return (std::max<float>)(0, dot(n, l)) * (std::max<float>)(0, dot(n, v));
|
||||
}
|
||||
|
||||
float G_Cook_Torrance(float3 n, float3 h, float3 v, float3 l) {
|
||||
float VdotH = dot(v, h) + 1e-5f;
|
||||
float NdotV = dot(n, v);
|
||||
float NdotH = dot(n, h);
|
||||
float NdotL = dot(n, l);
|
||||
|
||||
float g1 = (2.0f * dot(n, h) * NdotV) / VdotH;
|
||||
float g2 = (2.0f * dot(n, h) * dot(n, l)) / VdotH;
|
||||
return (std::min)(1.0f, (std::min)(g1, g2));
|
||||
}
|
||||
|
||||
|
||||
float D_BlinnPhong(lm::float3 h, lm::float3 n, float power) {
|
||||
float normalization = ((power + 2.0f) / (2.0f * MATH_PI));
|
||||
//float normalization = 1;
|
||||
//float normalization = ((power + 8) / (8.0f * MATH_PI));
|
||||
//float normalization = (power + 2) / (4 * MATH_PI*(2 - exp(-power / 2)));
|
||||
//float normalization = ((power + 2)*(power + 4)) / (2 * MATH_PI*(pow(2, -power / 2) + power));
|
||||
return normalization * std::pow((std::max)(0.0f, lm::dot(n, h)), power);
|
||||
}
|
||||
|
||||
float chiGGX(float v) {
|
||||
return v > 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
float GGX_Distribution(float3 n, float3 h, float alpha) {
|
||||
float NoH = dot(n, h);
|
||||
float alpha2 = alpha * alpha;
|
||||
float NoH2 = NoH * NoH;
|
||||
float den = NoH2 * alpha2 + (1 - NoH2);
|
||||
return (chiGGX(NoH) * alpha2) / (MATH_PI * den * den);
|
||||
}
|
||||
|
||||
float GGX_PartialGeometryTerm(float3 v, float3 n, float3 h, float alpha) {
|
||||
float VoH2 = (std::max)(0.0f, (dot(v, h)));
|
||||
float chi = chiGGX(VoH2 / (std::max)(0.0f, dot(v, n)));
|
||||
VoH2 = VoH2 * VoH2;
|
||||
float tan2 = (1.0f - VoH2) / VoH2;
|
||||
return (chi * 2.0f) / (1.0f + std::sqrt(1.0f + alpha * alpha * tan2));
|
||||
}
|
||||
|
||||
inline float D_Beckmann(lm::float3 h, lm::float3 n, float m) {
|
||||
float c = lm::dot(n, h);
|
||||
float T = c * c;
|
||||
float M = m*m;
|
||||
return std::exp((T - 1.0f) / (M*T)) / (M * T * T);
|
||||
}
|
||||
|
||||
float PhongToBeckmann(float a) {
|
||||
return std::sqrt(2.0f / (a + 2.0f));
|
||||
}
|
||||
|
||||
float BeckmannToPhong(float m) {
|
||||
return 2.0f / (m*m) - 2.0f;
|
||||
}
|
||||
|
||||
float Fresnel(float c, float ior) {
|
||||
float g = std::sqrt(ior*ior + c*c - 1);
|
||||
return 0.5f * std::pow(g - c, 2.0f) / std::pow(g + c, 2.0f) * (1.0f + std::pow(c*(g + c) - 1.0f, 2.0f) / std::pow(c*(g - c) + 1.0f, 2.0f));
|
||||
}
|
||||
#endif // lighting_core_h__
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
#ifndef BITMAP_H
|
||||
#define BITMAP_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
/*struct BITMAPFILEHEADER {
|
||||
int16 bfType;
|
||||
int32 bfSize;
|
||||
int16 Reserved1;
|
||||
int16 Reserved2;
|
||||
int32 bfOffBits;
|
||||
};*/
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include <Windows.h>
|
||||
#else
|
||||
#pragma pack(push,2)
|
||||
typedef struct tagBITMAPFILEHEADER {
|
||||
unsigned short bfType;
|
||||
unsigned long bfSize;
|
||||
unsigned short bfReserved1;
|
||||
unsigned short bfReserved2;
|
||||
unsigned long bfOffBits;
|
||||
} BITMAPFILEHEADER, *LPBITMAPFILEHEADER, *PBITMAPFILEHEADER;
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
#pragma pack(push,2)
|
||||
typedef struct tagBITMAPINFOHEADER {
|
||||
unsigned long biSize;
|
||||
long biWidth;
|
||||
long biHeight;
|
||||
unsigned short biPlanes;
|
||||
unsigned short biBitCount;
|
||||
unsigned long biCompression;
|
||||
unsigned long biSizeImage;
|
||||
long biXPelsPerMeter;
|
||||
long biYPelsPerMeter;
|
||||
unsigned long biClrUsed;
|
||||
unsigned long biClrImportant;
|
||||
}BITMAPINFOHEADER, *PBITMAPINFOHEADER;
|
||||
#pragma pack(pop)
|
||||
#endif
|
||||
|
||||
#endif // BITMAP_H
|
||||
+384
@@ -0,0 +1,384 @@
|
||||
#include "BlockRasterizer.h"
|
||||
#include "TextureSampler.h"
|
||||
#include <assert.h>
|
||||
#include <iostream>
|
||||
#include "ImageDataAccessorR5G6B5.h"
|
||||
#include "ImageDataAccessorR8G8B8.h"
|
||||
|
||||
BlockRasterizer::BlockRasterizer()
|
||||
:primitiveType(PT_TRIANGLE_LIST), vs(0), ps(0), geomLayout(0){
|
||||
|
||||
blendState.AlphaOperation = BLEND_OP_ADD;
|
||||
blendState.SrcAlpha = BLEND_SRC_ALPHA;
|
||||
blendState.DstAlpha = BLEND_INV_SRC_ALPHA;
|
||||
blendState.BlendEnable = false;
|
||||
|
||||
|
||||
NDCPlanes[0] = RasterizerPlane(1, 0, 0, 1);//left
|
||||
NDCPlanes[1] = RasterizerPlane(-1, 0, 0, 1);//right
|
||||
NDCPlanes[2] = RasterizerPlane(0, 1, 0, 1);//top
|
||||
NDCPlanes[3] = RasterizerPlane(0, -1, 0, 1);//bottom
|
||||
NDCPlanes[4] = RasterizerPlane(0, 0, 1, 0);//near plane (D3D NDC, NeraClip Z == 0)
|
||||
NDCPlanes[5] = RasterizerPlane(0, 0, -1, 1);//far
|
||||
|
||||
//NDCPlanes[6] = RasterizerPlane(0, 0, 0, 1);//WTF?
|
||||
}
|
||||
|
||||
BlockRasterizer::~BlockRasterizer() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool BlockRasterizer::ClipToFrustumPlane(RasterizerPlane plane, ClipVector& src, ClipVector& dst, size_t regCount) {
|
||||
auto face_count = src.size();
|
||||
bool clipped = false;
|
||||
for (size_t i = 0; i < face_count; i++) {
|
||||
//read face from input
|
||||
ClipFace face = src[i];
|
||||
int v0out, v1out, v2out, vout_cnt;
|
||||
v0out = v1out = v2out = vout_cnt = 0;
|
||||
if (lm::dot(plane, face.v0.reg[0]) <= 0) { v0out++; vout_cnt++; }
|
||||
if (lm::dot(plane, face.v1.reg[0]) <= 0) { v1out++; vout_cnt++; }
|
||||
if (lm::dot(plane, face.v2.reg[0]) <= 0) { v2out++; vout_cnt++; }
|
||||
|
||||
|
||||
switch (vout_cnt) {
|
||||
case 3://all 3 vertices behind plane! Clip entire triangle
|
||||
clipped = true;
|
||||
continue;
|
||||
case 2:
|
||||
{
|
||||
//printf("2 vertices behind plane!\n");
|
||||
clipped = true;
|
||||
RegisterBlock* vert[3];
|
||||
RegisterBlock vA, vB;
|
||||
if (v0out && v1out) { vert[0] = &face.v0; vert[1] = &face.v1; vert[2] = &face.v2; }
|
||||
if (v1out && v2out) { vert[0] = &face.v1; vert[1] = &face.v2; vert[2] = &face.v0; }
|
||||
if (v2out && v0out) { vert[0] = &face.v2; vert[1] = &face.v0; vert[2] = &face.v1; }
|
||||
|
||||
float alpha_a = lm::dot(plane, vert[2]->reg[0]) / (lm::dot(plane, vert[2]->reg[0]) - lm::dot(plane, vert[1]->reg[0]));
|
||||
float alpha_b = lm::dot(plane, vert[2]->reg[0]) / (lm::dot(plane, vert[2]->reg[0]) - lm::dot(plane, vert[0]->reg[0]));
|
||||
|
||||
for (size_t k = 0; k < regCount; k++) {
|
||||
vA.reg[k] = vert[2]->reg[k] + (vert[1]->reg[k] - vert[2]->reg[k]) * alpha_a;
|
||||
vB.reg[k] = vert[2]->reg[k] + (vert[0]->reg[k] - vert[2]->reg[k]) * alpha_b;
|
||||
}
|
||||
|
||||
ClipFace fa;
|
||||
fa.v0 = vA;
|
||||
fa.v1 = *vert[2];
|
||||
fa.v2 = vB;
|
||||
dst.push_back(fa);
|
||||
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
{
|
||||
clipped = true;
|
||||
RegisterBlock* vert[3];
|
||||
RegisterBlock vA, vB;
|
||||
if (v0out) { vert[0] = &face.v0; vert[1] = &face.v1; vert[2] = &face.v2; }
|
||||
if (v1out) { vert[0] = &face.v1; vert[1] = &face.v2; vert[2] = &face.v0; }
|
||||
if (v2out) { vert[0] = &face.v2; vert[1] = &face.v0; vert[2] = &face.v1; }
|
||||
|
||||
float alpha_a = lm::dot(plane, vert[2]->reg[0]) / (lm::dot(plane, vert[2]->reg[0]) - lm::dot(plane, vert[0]->reg[0]));
|
||||
float alpha_b = lm::dot(plane, vert[1]->reg[0]) / (lm::dot(plane, vert[1]->reg[0]) - lm::dot(plane, vert[0]->reg[0]));
|
||||
|
||||
for (size_t k = 0; k < regCount; k++) {
|
||||
vA.reg[k] = vert[2]->reg[k] + (vert[0]->reg[k] - vert[2]->reg[k]) * alpha_a;
|
||||
vB.reg[k] = vert[1]->reg[k] + (vert[0]->reg[k] - vert[1]->reg[k]) * alpha_b;
|
||||
}
|
||||
|
||||
ClipFace fa;
|
||||
fa.v0 = vB;
|
||||
fa.v1 = *vert[1];
|
||||
fa.v2 = vA;
|
||||
dst.push_back(fa);
|
||||
|
||||
ClipFace fb;
|
||||
fb.v0 = vA;
|
||||
fb.v1 = *vert[1];
|
||||
fb.v2 = *vert[2];
|
||||
dst.push_back(fb);
|
||||
|
||||
//DrawTriangle(rA_out, *vert[1], *vert[2]);
|
||||
}
|
||||
break;
|
||||
case 0:
|
||||
dst.push_back(face); //nothing to crop! Just push it
|
||||
break;
|
||||
}
|
||||
}
|
||||
return clipped;
|
||||
}
|
||||
|
||||
void BlockRasterizer::ClipToFrustum(ClipFace face, ClipVector& dst, size_t regCount) {
|
||||
|
||||
cv1.clear();
|
||||
cv2.clear();
|
||||
|
||||
dst.clear();
|
||||
|
||||
cv1.push_back(face);
|
||||
|
||||
if(ClipToFrustumPlane(NDCPlanes[0], cv1, cv2, regCount)){
|
||||
std::cout << "Clipped with plane 0" << std::endl;
|
||||
}
|
||||
cv1.clear();
|
||||
|
||||
if (ClipToFrustumPlane(NDCPlanes[1], cv2, cv1, regCount)) {
|
||||
std::cout << "Clipped with plane 1" << std::endl;
|
||||
}
|
||||
cv2.clear();
|
||||
|
||||
if (ClipToFrustumPlane(NDCPlanes[2], cv1, cv2, regCount)) {
|
||||
std::cout << "Clipped with plane 2" << std::endl;
|
||||
}
|
||||
cv1.clear();
|
||||
|
||||
if (ClipToFrustumPlane(NDCPlanes[3], cv2, cv1, regCount)) {
|
||||
std::cout << "Clipped with plane 3" << std::endl;
|
||||
}
|
||||
cv2.clear();
|
||||
|
||||
if (ClipToFrustumPlane(NDCPlanes[4], cv1, cv2, regCount)) {
|
||||
std::cout << "Clipped with plane 4" << std::endl;
|
||||
}
|
||||
//cv1.clear();
|
||||
|
||||
if (ClipToFrustumPlane(NDCPlanes[5], cv2, dst, regCount)) {
|
||||
std::cout << "Clipped with plane 5" << std::endl;
|
||||
}
|
||||
/*if (ClipToFrustumPlane(NDCPlanes[6], cv1, dst)) {
|
||||
std::cout << "Clipped with plane 6" << std::endl;
|
||||
}*/
|
||||
}
|
||||
|
||||
Texture* BlockRasterizer::GetBackBuffer() {
|
||||
return backBuffer;
|
||||
}
|
||||
|
||||
Texture* BlockRasterizer::GetDepthBuffer() {
|
||||
return depthBuffer;
|
||||
}
|
||||
|
||||
void BlockRasterizer::setColorBuffer(Texture* buffer) {
|
||||
backBuffer = buffer;
|
||||
}
|
||||
|
||||
void BlockRasterizer::setDepthBuffer(Texture* buffer) {
|
||||
depthBuffer = buffer;
|
||||
}
|
||||
|
||||
void BlockRasterizer::SetPrimitiveType(int type) {
|
||||
primitiveType = type;
|
||||
}
|
||||
|
||||
void BlockRasterizer::Draw(size_t offset, size_t length) {
|
||||
if (!length) return;
|
||||
switch (primitiveType) {
|
||||
case PT_TRIANGLE_LIST:
|
||||
{
|
||||
auto faceCount = length / 3;
|
||||
Buffer* geom = vbSlots[0].buffer;
|
||||
|
||||
if (!faceCount){
|
||||
DebugInfo("No faces to draw");
|
||||
return;
|
||||
}
|
||||
if (!geom){
|
||||
DebugError("Vertex Buffer is not set");
|
||||
return;
|
||||
}
|
||||
|
||||
auto stride = vbSlots[0].stride;
|
||||
|
||||
//Buffer is too small for this draw call
|
||||
if (geom->Size() / stride < faceCount * 3) {
|
||||
DebugError("[Draw] Vertex Buffer is too small!");
|
||||
return;
|
||||
}
|
||||
uint8_t* data = (uint8_t*)geom->GetPointer();
|
||||
for (size_t i = 0; i < faceCount; i++) {
|
||||
//setup vertex data pointers
|
||||
uint8_t* v0 = data + ((offset + 0 + i * 3) * stride);
|
||||
uint8_t* v1 = data + ((offset + 1 + i * 3) * stride);
|
||||
uint8_t* v2 = data + ((offset + 2 + i * 3) * stride);
|
||||
draw_impl(v0, v1, v2);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void BlockRasterizer::DrawIndexed(size_t index_count, size_t start_index_location)
|
||||
{
|
||||
if (index_count == 0) return;
|
||||
switch (primitiveType) {
|
||||
case PT_TRIANGLE_LIST:
|
||||
{
|
||||
int faceCount = index_count / 3;
|
||||
Buffer* geom = vbSlots[0].buffer;
|
||||
Buffer* indices = ibSlots[0];
|
||||
|
||||
if (!faceCount) {
|
||||
DebugInfo("No faces to draw");
|
||||
return;
|
||||
}
|
||||
if (!geom) {
|
||||
DebugError("Vertex Buffer is not set");
|
||||
return;
|
||||
}
|
||||
if (!indices) {
|
||||
DebugError("Index Buffer is not set");
|
||||
return;
|
||||
}
|
||||
int stride = vbSlots[0].stride;
|
||||
|
||||
uint8_t* vertex_data = (uint8_t*)geom->GetPointer();
|
||||
auto vertices_count = geom->Size() / vbSlots[0].stride;
|
||||
indices_t* index_data = (indices_t*)indices->GetPointer();
|
||||
|
||||
for (size_t i = 0; i < index_count; i+=3) {
|
||||
//setup vertex data pointers
|
||||
auto id0 = index_data[i + 0 + start_index_location];
|
||||
auto id1 = index_data[i + 1 + start_index_location];
|
||||
auto id2 = index_data[i + 2 + start_index_location];
|
||||
|
||||
uint8_t* v0 = vertex_data + id0 * stride;
|
||||
uint8_t* v1 = vertex_data + id1 * stride;
|
||||
uint8_t* v2 = vertex_data + id2 * stride;
|
||||
draw_impl(v0, v1, v2);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void BlockRasterizer::draw_impl(void* v0, void* v1, void* v2)
|
||||
{
|
||||
int elements = geomLayout->Size();
|
||||
for (int i = 0; i < elements; i++) { //TODO: OMG WTF! Fix memory corruption!!!
|
||||
InputElement* e = geomLayout->GetElement(i);
|
||||
int rd = regMapping[i];
|
||||
if(rd >= 0){
|
||||
r0_in[rd] = reinterpret_cast<float4*>((uint8_t*)v0 + e->Offset);
|
||||
r1_in[rd] = reinterpret_cast<float4*>((uint8_t*)v1 + e->Offset);
|
||||
r2_in[rd] = reinterpret_cast<float4*>((uint8_t*)v2 + e->Offset);
|
||||
}
|
||||
}
|
||||
vs->Execute(&r0_in[0], &r0_out.reg[0]);
|
||||
vs->Execute(&r1_in[0], &r1_out.reg[0]);
|
||||
int numInterpolators = vs->Execute(&r2_in[0], &r2_out.reg[0]);
|
||||
|
||||
|
||||
//r0_out.reg[0].y() = -r0_out.reg[0].y();
|
||||
//r1_out.reg[0].y() = -r1_out.reg[0].y();
|
||||
//r2_out.reg[0].y() = -r2_out.reg[0].y();
|
||||
|
||||
ClipVector cv;
|
||||
ClipFace cf;
|
||||
cf.v0 = r0_out;
|
||||
cf.v1 = r1_out;
|
||||
cf.v2 = r2_out;
|
||||
|
||||
ClipToFrustum(cf, cv, numInterpolators);
|
||||
|
||||
|
||||
auto bbDesc = backBuffer->Desc();
|
||||
|
||||
|
||||
if (bbDesc.BytesPerPixel == 4) {
|
||||
for (size_t l = 0; l < cv.size(); l++) {
|
||||
ClipFace cf_render = cv[l];
|
||||
DrawTriangle<ImageDataAccessorR8G8B8>(cf_render.v0, cf_render.v1, cf_render.v2);
|
||||
}
|
||||
}
|
||||
else if (bbDesc.BytesPerPixel == 2) {
|
||||
for (size_t l = 0; l < cv.size(); l++) {
|
||||
ClipFace cf_render = cv[l];
|
||||
DrawTriangle<ImageDataAccessorR5G6B5>(cf_render.v0, cf_render.v1, cf_render.v2);
|
||||
}
|
||||
}
|
||||
else {
|
||||
//Not supported
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void BlockRasterizer::FixupMapping() {
|
||||
if (geomLayout != 0) {
|
||||
if (vs != 0) {
|
||||
auto elements = geomLayout->Size();
|
||||
for (size_t i = 0; i < elements; i++) {
|
||||
regMapping[i] = vs->FindRegister(geomLayout->GetElement(i)->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BlockRasterizer::SetVertexBuffer(Buffer* vb, size_t slot, size_t stride) {
|
||||
vbSlots[slot].buffer = vb;
|
||||
vbSlots[slot].stride = stride;
|
||||
}
|
||||
|
||||
void BlockRasterizer::SetIndexBuffer(Buffer* ib, size_t slot){
|
||||
ibSlots[slot] = ib;
|
||||
}
|
||||
|
||||
void BlockRasterizer::SetInputLayout(IInputLayout* layout) {
|
||||
geomLayout = layout;
|
||||
FixupMapping();
|
||||
}
|
||||
|
||||
void BlockRasterizer::SetPixelShader(PixelShader* shader) {
|
||||
ps = shader;
|
||||
}
|
||||
|
||||
void BlockRasterizer::SetVertexShader(VertexShader* shader) {
|
||||
vs = shader;
|
||||
FixupMapping();
|
||||
}
|
||||
|
||||
void BlockRasterizer::SetBlendState(BlendState* state) {
|
||||
blendState = *state;
|
||||
}
|
||||
|
||||
float BlockRasterizer::GetBlendAlpha(BLEND_SOURCE src, const float4& srcColor, const float4& dstColor) {
|
||||
switch (src) {
|
||||
case BLEND_ZERO:
|
||||
return 0.0f;
|
||||
case BLEND_ONE:
|
||||
return 1.0f;
|
||||
case BLEND_SRC_ALPHA:
|
||||
return srcColor.w();
|
||||
case BLEND_INV_SRC_ALPHA:
|
||||
return 1.0f - srcColor.w();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t BlockRasterizer::ConvertColor(const float4& color) {
|
||||
uint32_t r = (uint32_t)(color.x() * 255.0f);
|
||||
uint32_t g = (uint32_t)(color.y() * 255.0f);
|
||||
uint32_t b = (uint32_t)(color.z() * 255.0f);
|
||||
uint32_t a = (uint32_t)(color.w() * 255.0f);
|
||||
|
||||
return (a << 24) | (r << 16) | (g << 8) | (b);
|
||||
}
|
||||
|
||||
float4 BlockRasterizer::ConvertColor(uint32_t color) {
|
||||
float d = 1.0f / 255.0f;
|
||||
|
||||
float a = (float)((color >> 24) & 0xff) * d;
|
||||
float r = (float)((color >> 16) & 0xff) * d;
|
||||
float g = (float)((color >> 8) & 0xff) * d;
|
||||
float b = (float)((color >> 0) & 0xff) * d;
|
||||
|
||||
return float4(r, g, b, a);
|
||||
}
|
||||
|
||||
+483
@@ -0,0 +1,483 @@
|
||||
#ifndef BlockRasterizer_h__
|
||||
#define BlockRasterizer_h__
|
||||
|
||||
#include "Texture.h"
|
||||
#include "Viewport.h"
|
||||
#include "InputLayout.h"
|
||||
#include "VertexShader.h"
|
||||
#include "PixelShader.h"
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include "Tools.h"
|
||||
#include <vector>
|
||||
#include "IRenderWindow.h"
|
||||
#include "static_vector.h"
|
||||
#include "RasterizerSettings.h"
|
||||
#include <array>
|
||||
#include "Debug.h"
|
||||
#include "RegisterBlock.h"
|
||||
#include <LMath/lmath.h>
|
||||
|
||||
using namespace lm;
|
||||
|
||||
enum PRIMITIVE_TYPE
|
||||
{
|
||||
PT_TRIANGLE_LIST = 0,
|
||||
PT_TRIANGLE_STRIP = 1,
|
||||
PT_LINE_LIST = 2,
|
||||
PT_LINE_STRIP = 3,
|
||||
PT_POINT_LIST = 4
|
||||
|
||||
};
|
||||
enum BLEND_SOURCE
|
||||
{
|
||||
BLEND_ZERO = 0,
|
||||
BLEND_ONE = 1,
|
||||
BLEND_SRC_ALPHA = 3,
|
||||
BLEND_INV_SRC_ALPHA = 4
|
||||
};
|
||||
enum BLEND_OP
|
||||
{
|
||||
BLEND_OP_ADD = 0
|
||||
};
|
||||
struct BlendState
|
||||
{
|
||||
BLEND_SOURCE SrcAlpha;
|
||||
BLEND_SOURCE DstAlpha;
|
||||
BLEND_OP AlphaOperation;
|
||||
bool BlendEnable;
|
||||
};
|
||||
enum NDCZone
|
||||
{
|
||||
ZONE_ZERO = 0,
|
||||
ZONE_LEFT = 1,
|
||||
ZONE_RIGHT = 2,
|
||||
ZONE_BOTTOM = 3,
|
||||
ZONE_TOP = 4,
|
||||
ZONE_FAR = 5,
|
||||
ZONE_NEAR = 6
|
||||
};
|
||||
|
||||
static constexpr const char* NDCZoneStr[7]{
|
||||
"ZONE_ZERO",
|
||||
"ZONE_LEFT",
|
||||
"ZONE_RIGHT",
|
||||
"ZONE_BOTTOM",
|
||||
"ZONE_TOP",
|
||||
"ZONE_FAR",
|
||||
"ZONE_NEAR"
|
||||
};
|
||||
|
||||
struct ClipFace
|
||||
{
|
||||
RegisterBlock v0;
|
||||
RegisterBlock v1;
|
||||
RegisterBlock v2;
|
||||
};
|
||||
|
||||
|
||||
class BlockRasterizer {
|
||||
public:
|
||||
typedef Plane<float> RasterizerPlane;
|
||||
typedef Static_vector<ClipFace, 9> ClipVector;
|
||||
|
||||
BlockRasterizer();
|
||||
~BlockRasterizer();
|
||||
bool ClipToFrustumPlane(RasterizerPlane plane, ClipVector& src, ClipVector& dst, size_t regCount);
|
||||
void ClipToFrustum(ClipFace face, ClipVector& dst, size_t regCount);
|
||||
Texture* GetBackBuffer();
|
||||
Texture* GetDepthBuffer();
|
||||
|
||||
void setColorBuffer(Texture* buffer);
|
||||
void setDepthBuffer(Texture* buffer);
|
||||
|
||||
void SetPrimitiveType(int type);
|
||||
void Draw(size_t offset, size_t length);
|
||||
void DrawIndexed(size_t index_count, size_t start_index_location);
|
||||
void FixupMapping();
|
||||
void SetVertexBuffer(Buffer* vb, size_t slot, size_t stride);
|
||||
void SetIndexBuffer(Buffer* ib, size_t slot);
|
||||
|
||||
void SetInputLayout(IInputLayout* layout);
|
||||
void SetPixelShader(PixelShader* shader);
|
||||
void SetVertexShader(VertexShader* shader);
|
||||
void SetBlendState(BlendState* state);
|
||||
|
||||
float GetBlendAlpha(BLEND_SOURCE src, const float4& srcColor, const float4& dstColor);
|
||||
private:
|
||||
ClipVector cv1, cv2;
|
||||
void draw_impl(void* v0, void* v1, void* v2);
|
||||
|
||||
IRenderWindow* render_window;
|
||||
std::array<RasterizerPlane, 6> NDCPlanes;
|
||||
|
||||
uint32_t ConvertColor(const float4& color);
|
||||
float4 ConvertColor(uint32_t color);
|
||||
|
||||
|
||||
template<size_t _BlockSize, typename _Var>
|
||||
inline void CalcDerivatives(
|
||||
int dy10, int dy20,
|
||||
int dx10, int dx20,
|
||||
_Var z0, _Var z1, _Var z2, _Var& ddx, _Var& ddy) {
|
||||
|
||||
const auto dc10 = z1 - z0;
|
||||
const auto dc20 = z2 - z0;
|
||||
|
||||
//(iy1 - iy0)
|
||||
auto A = dc20 * dy10 - dc10 * dy20;
|
||||
auto B = dc10 * dx20 - dc20 * dx10;
|
||||
int C = dy20 * dx10 - dx20 * dy10;
|
||||
|
||||
ddx = A / (float)-C;
|
||||
ddy = B / (float)-C;
|
||||
}
|
||||
|
||||
|
||||
template<typename ColorDataAccessor>
|
||||
void DrawTriangle(RegisterBlock r0_src, RegisterBlock r1_src, RegisterBlock r2_src) {
|
||||
float scrW_h = (float)(backBuffer->Desc().Width / 2);
|
||||
float scrH_h = (float)(backBuffer->Desc().Height / 2);
|
||||
|
||||
RegisterBlock* p0 = &r0_src;
|
||||
RegisterBlock* p1 = &r1_src;
|
||||
RegisterBlock* p2 = &r2_src;
|
||||
|
||||
//p1->reg[0].W = abs(p1->reg[0].W);
|
||||
float iw0 = 1.0f / p0->reg[0].w();
|
||||
float iw1 = 1.0f / p1->reg[0].w();
|
||||
float iw2 = 1.0f / p2->reg[0].w();
|
||||
|
||||
//transform vertices to viewport space
|
||||
p0->reg[0].x() = (p0->reg[0].x() * iw0) * scrW_h + scrW_h;
|
||||
p0->reg[0].y() = (p0->reg[0].y() * iw0) * scrH_h + scrH_h;
|
||||
p0->reg[0].z() = (p0->reg[0].z() * iw0);
|
||||
|
||||
p1->reg[0].x() = (p1->reg[0].x() * iw1) * scrW_h + scrW_h;
|
||||
p1->reg[0].y() = (p1->reg[0].y() * iw1) * scrH_h + scrH_h;
|
||||
p1->reg[0].z() = (p1->reg[0].z() * iw1);
|
||||
|
||||
p2->reg[0].x() = (p2->reg[0].x() * iw2) * scrW_h + scrW_h;
|
||||
p2->reg[0].y() = (p2->reg[0].y() * iw2) * scrH_h + scrH_h;
|
||||
p2->reg[0].z() = (p2->reg[0].z() * iw2);
|
||||
|
||||
float3 camZ(p0->reg[0].z(), p1->reg[0].z(), p2->reg[0].z());
|
||||
|
||||
bool disableCulling = false;
|
||||
if (disableCulling)
|
||||
if (((p1->reg[0].x() - p0->reg[0].x()) * (p2->reg[0].y() - p0->reg[0].y()) - (p1->reg[0].y() - p0->reg[0].y()) * (p2->reg[0].x() - p0->reg[0].x()) <= 0)) {
|
||||
RegisterBlock* pTmp = p0;
|
||||
p0 = p2;
|
||||
p2 = pTmp;
|
||||
}
|
||||
|
||||
|
||||
const int x0 = (int)std::round(16.0f * p0->reg[0].x());
|
||||
const int x1 = (int)std::round(16.0f * p1->reg[0].x());
|
||||
const int x2 = (int)std::round(16.0f * p2->reg[0].x());
|
||||
const int y0 = (int)std::round(16.0f * p0->reg[0].y());
|
||||
const int y1 = (int)std::round(16.0f * p1->reg[0].y());
|
||||
const int y2 = (int)std::round(16.0f * p2->reg[0].y());
|
||||
|
||||
const int Dx01 = x0 - x1;
|
||||
const int Dx12 = x1 - x2;
|
||||
const int Dx20 = x2 - x0;
|
||||
|
||||
const int Dy01 = y0 - y1;
|
||||
const int Dy12 = y1 - y2;
|
||||
const int Dy20 = y2 - y0;
|
||||
|
||||
const int FDx01 = Dx01 << 4;
|
||||
const int FDx12 = Dx12 << 4;
|
||||
const int FDx20 = Dx20 << 4;
|
||||
|
||||
const int FDy01 = Dy01 << 4;
|
||||
const int FDy12 = Dy12 << 4;
|
||||
const int FDy20 = Dy20 << 4;
|
||||
|
||||
//bounding rectangle
|
||||
int minX = ((std::min)((std::min)(x0, x1), x2) + 0xF) >> 4;
|
||||
int maxX = ((std::max)((std::max)(x0, x1), x2) + 0xF) >> 4;
|
||||
int minY = ((std::min)((std::min)(y0, y1), y2) + 0xF) >> 4;
|
||||
int maxY = ((std::max)((std::max)(y0, y1), y2) + 0xF) >> 4;
|
||||
|
||||
const int ix0 = (x0 + 0xf) >> 4;
|
||||
const int ix1 = (x1 + 0xf) >> 4;
|
||||
const int ix2 = (x2 + 0xf) >> 4;
|
||||
|
||||
const int iy0 = (y0 + 0xf) >> 4;
|
||||
const int iy1 = (y1 + 0xf) >> 4;
|
||||
const int iy2 = (y2 + 0xf) >> 4;
|
||||
|
||||
const int diy20 = iy2 - iy0;
|
||||
const int dix20 = ix2 - ix0;
|
||||
const int diy10 = iy1 - iy0;
|
||||
const int dix10 = ix1 - ix0;
|
||||
|
||||
const int area = dix10 * diy20 - dix20 * diy10;
|
||||
|
||||
if (area == 0) return;
|
||||
|
||||
|
||||
if (maxY < 0)
|
||||
return;
|
||||
if (minY >= (int)backBuffer->Desc().Height)
|
||||
return;
|
||||
if (maxX < 0)
|
||||
return;
|
||||
if (minX >= (int)backBuffer->Desc().Width)
|
||||
return;
|
||||
|
||||
if (minY < 0)
|
||||
minY = 0;
|
||||
if (maxY >= (int)backBuffer->Desc().Height)
|
||||
maxY = (int)backBuffer->Desc().Height - 1;
|
||||
|
||||
if (minX < 0)
|
||||
minX = 0;
|
||||
if (maxX >= (int)backBuffer->Desc().Width)
|
||||
maxX = (int)backBuffer->Desc().Width - 1;
|
||||
|
||||
|
||||
int blockSize = 8;
|
||||
|
||||
minX &= ~(blockSize - 1);
|
||||
minY &= ~(blockSize - 1);
|
||||
|
||||
auto bbPtr = reinterpret_cast<typename ColorDataAccessor::PixelDataType*>(backBuffer->LockWrite());
|
||||
|
||||
auto dbPtr = reinterpret_cast<float*>(depthBuffer->LockWrite());
|
||||
|
||||
bbPtr += minY * backBuffer->Desc().Width;
|
||||
dbPtr += minY * depthBuffer->Desc().Width;
|
||||
|
||||
int C1 = Dy01 * x0 - Dx01 * y0;
|
||||
int C2 = Dy12 * x1 - Dx12 * y1;
|
||||
int C3 = Dy20 * x2 - Dx20 * y2;
|
||||
|
||||
|
||||
//top-left fill convention fix
|
||||
if (!(Dy01 < 0 || (Dy01 == 0 && Dx01 > 0))) C1--;
|
||||
if (!(Dy12 < 0 || (Dy12 == 0 && Dx12 > 0))) C2--;
|
||||
if (!(Dy20 < 0 || (Dy20 == 0 && Dx20 > 0))) C3--;
|
||||
|
||||
RegisterBlock triDerivX;
|
||||
RegisterBlock triDerivY;
|
||||
|
||||
RegisterBlock invRegs[3];
|
||||
for (int i = 1; i < REG_COUNT; i++) {
|
||||
invRegs[0].reg[i] = p0->reg[i] * iw0;
|
||||
invRegs[1].reg[i] = p1->reg[i] * iw1;
|
||||
invRegs[2].reg[i] = p2->reg[i] * iw2;
|
||||
}
|
||||
|
||||
for (int i = 1; i < REG_COUNT; i++) {
|
||||
CalcDerivatives<8, float4>(diy10, diy20, dix10, dix20, invRegs[0].reg[i], invRegs[1].reg[i], invRegs[2].reg[i], triDerivX.reg[i], triDerivY.reg[i]);
|
||||
}
|
||||
float2 derivZW_X;
|
||||
float2 derivZW_Y;
|
||||
|
||||
float2 p0zw = p0->reg[0].zw();
|
||||
p0zw.y() = 1.0f / p0zw.y();
|
||||
|
||||
float2 p1zw = p1->reg[0].zw();
|
||||
p1zw.y() = 1.0f / p1zw.y();
|
||||
|
||||
float2 p2zw = p2->reg[0].zw();
|
||||
p2zw.y() = 1.0f / p2zw.y();
|
||||
|
||||
CalcDerivatives<8, float2>(diy10, diy20, dix10, dix20, p0zw, p1zw, p2zw, derivZW_X, derivZW_Y);
|
||||
|
||||
//scan all blocks
|
||||
for (int y = minY; y < maxY; y += blockSize) {
|
||||
for (int x = minX; x < maxX; x += blockSize) {
|
||||
//find block corners
|
||||
int x0 = x << 4;
|
||||
int x1 = (x + blockSize - 1) << 4;
|
||||
int y0 = y << 4;
|
||||
int y1 = (y + blockSize - 1) << 4;
|
||||
|
||||
//evaluate half space functions for each corner
|
||||
bool a00 = C1 + Dx01 * y0 - Dy01 * x0 < 0;
|
||||
bool a01 = C1 + Dx01 * y0 - Dy01 * x1 < 0;
|
||||
bool a10 = C1 + Dx01 * y1 - Dy01 * x0 < 0;
|
||||
bool a11 = C1 + Dx01 * y1 - Dy01 * x1 < 0;
|
||||
int a = (a00 << 0) | (a10 << 1) | (a01 << 2) | (a11 << 3);
|
||||
|
||||
bool b00 = C2 + Dx12 * y0 - Dy12 * x0 < 0;
|
||||
bool b01 = C2 + Dx12 * y0 - Dy12 * x1 < 0;
|
||||
bool b10 = C2 + Dx12 * y1 - Dy12 * x0 < 0;
|
||||
bool b11 = C2 + Dx12 * y1 - Dy12 * x1 < 0;
|
||||
int b = (b00 << 0) | (b10 << 1) | (b01 << 2) | (b11 << 3);
|
||||
|
||||
bool c00 = C3 + Dx20 * y0 - Dy20 * x0 < 0;
|
||||
bool c01 = C3 + Dx20 * y0 - Dy20 * x1 < 0;
|
||||
bool c10 = C3 + Dx20 * y1 - Dy20 * x0 < 0;
|
||||
bool c11 = C3 + Dx20 * y1 - Dy20 * x1 < 0;
|
||||
int c = ((uint32_t)c00 << 0) | ((uint32_t)c10 << 1) | ((uint32_t)c01 << 2) | ((uint32_t)c11 << 3);
|
||||
|
||||
//Skip entire block if all it's 4 corners outside of triangle edges
|
||||
if (a == 0 || b == 0 || c == 0)
|
||||
continue;
|
||||
|
||||
auto colorBuffer = bbPtr;
|
||||
auto zBuffer = dbPtr;
|
||||
|
||||
RegisterBlock var00;
|
||||
//interpolate registers
|
||||
for (int r = 1; r < REG_COUNT; r++) {
|
||||
var00.reg[r] = invRegs[0].reg[r] + triDerivX.reg[r] * (x - ix0) + triDerivY.reg[r] * (y - iy0);
|
||||
}
|
||||
|
||||
//Whole block is inside triangle!
|
||||
if (a == 0xf && b == 0xf && c == 0xf) {
|
||||
for (int by = 0; by < blockSize; by++) {
|
||||
for (int bx = x; bx < (x + blockSize); bx++) {
|
||||
//compute interpolation weights
|
||||
|
||||
auto ddx0 = (bx - ix0);
|
||||
auto ddy0 = (y + by - iy0);
|
||||
float2 zw = p0zw + derivZW_X * ddx0 + derivZW_Y * ddy0;
|
||||
|
||||
//interpolate Z
|
||||
float z_interp = zw.x();
|
||||
|
||||
if (zBuffer[bx] > z_interp)
|
||||
{
|
||||
zBuffer[bx] = z_interp;
|
||||
//interpolate registers
|
||||
|
||||
for (int r = 1; r < REG_COUNT; r++) {
|
||||
r_ps.reg[r] = (var00.reg[r] + triDerivX.reg[r] * (bx - x)) / zw.y();
|
||||
}
|
||||
|
||||
/*for (int r = 1; r < REG_COUNT; r++) {
|
||||
r_ps.reg[r] = invRegs[0].reg[r] + triDerivX.reg[r] * ddx0 + triDerivY.reg[r] * ddy0;
|
||||
}*/
|
||||
|
||||
float4 pixel_color = ps->Execute(&r_ps.reg[0]);
|
||||
|
||||
if (blendState.BlendEnable) {
|
||||
uint32_t dc = colorBuffer[bx];
|
||||
|
||||
float4 dstColor = ColorDataAccessor::ConvertColor(dc);
|
||||
|
||||
//get source alpha
|
||||
float srcAlpha = GetBlendAlpha(blendState.SrcAlpha, pixel_color, dstColor);
|
||||
float dstAlpha = GetBlendAlpha(blendState.DstAlpha, pixel_color, dstColor);
|
||||
|
||||
pixel_color = pixel_color * srcAlpha + dstColor * dstAlpha;
|
||||
}
|
||||
//colorBuffer[bx] += 0x00606060;
|
||||
colorBuffer[bx] = ColorDataAccessor::ConvertColor(pixel_color);
|
||||
}
|
||||
}
|
||||
colorBuffer += backBuffer->Desc().Width;
|
||||
zBuffer += depthBuffer->Desc().Width;
|
||||
|
||||
//increment Y variables
|
||||
for (int r = 1; r < REG_COUNT; r++) {
|
||||
var00.reg[r] = var00.reg[r] + triDerivY.reg[r];
|
||||
}
|
||||
}
|
||||
}
|
||||
else //Partially covered block
|
||||
{
|
||||
int CY1 = C1 + Dx01 * y0 - Dy01 * x0;
|
||||
int CY2 = C2 + Dx12 * y0 - Dy12 * x0;
|
||||
int CY3 = C3 + Dx20 * y0 - Dy20 * x0;
|
||||
|
||||
for (int by = y; by < (y + blockSize); by++) {
|
||||
int CX1 = CY1;
|
||||
int CX2 = CY2;
|
||||
int CX3 = CY3;
|
||||
|
||||
for (int bx = x; bx < (x + blockSize); bx++) {
|
||||
if (CX1 < 0 && CX2 < 0 && CX3 < 0) {
|
||||
auto ddx0 = bx - ix0;
|
||||
auto ddy0 = (by - iy0);
|
||||
float2 zw = p0zw + derivZW_X * ddx0 + derivZW_Y * ddy0;
|
||||
|
||||
float z_interp = zw.x();
|
||||
|
||||
if (zBuffer[bx] > z_interp) {
|
||||
zBuffer[bx] = z_interp;
|
||||
//interpolate registers
|
||||
for (int r = 1; r < REG_COUNT; r++) {
|
||||
r_ps.reg[r] = invRegs[0].reg[r] + triDerivX.reg[r] * ddx0 + triDerivY.reg[r] * ddy0;
|
||||
r_ps.reg[r] /= zw.y();//add perspective correction
|
||||
}
|
||||
|
||||
float4 rst;
|
||||
rst = ps->Execute(&r_ps.reg[0]);
|
||||
|
||||
//UINT texcolor = ConvertColor(rst);
|
||||
|
||||
if (blendState.BlendEnable) {
|
||||
uint32_t dc = colorBuffer[bx];
|
||||
|
||||
float4 dstColor = ColorDataAccessor::ConvertColor(dc);
|
||||
|
||||
float srcAlpha;
|
||||
float dstAlpha;
|
||||
|
||||
//get source alpha
|
||||
srcAlpha = GetBlendAlpha(blendState.SrcAlpha, rst, dstColor);
|
||||
dstAlpha = GetBlendAlpha(blendState.DstAlpha, rst, dstColor);
|
||||
|
||||
rst = rst * srcAlpha + dstColor * dstAlpha;
|
||||
}
|
||||
//colorBuffer[bx] += 0x00606060;
|
||||
colorBuffer[bx] = ColorDataAccessor::ConvertColor(rst);
|
||||
}
|
||||
}
|
||||
|
||||
CX1 -= FDy01;
|
||||
CX2 -= FDy12;
|
||||
CX3 -= FDy20;
|
||||
}
|
||||
CY1 += FDx01;
|
||||
CY2 += FDx12;
|
||||
CY3 += FDx20;
|
||||
|
||||
colorBuffer += backBuffer->Desc().Width;
|
||||
zBuffer += depthBuffer->Desc().Width;
|
||||
}
|
||||
}
|
||||
}
|
||||
bbPtr += backBuffer->Desc().Width * blockSize;
|
||||
dbPtr += depthBuffer->Desc().Width * blockSize;
|
||||
}
|
||||
}
|
||||
|
||||
std::array<float4*, REG_COUNT> r0_in;
|
||||
std::array<float4*, REG_COUNT> r1_in;
|
||||
std::array<float4*, REG_COUNT> r2_in;
|
||||
|
||||
RegisterBlock r0_out;
|
||||
RegisterBlock r1_out;
|
||||
RegisterBlock r2_out;
|
||||
RegisterBlock rA_out;
|
||||
RegisterBlock rB_out;
|
||||
RegisterBlock r_ps;
|
||||
|
||||
BlendState blendState;
|
||||
|
||||
IInputLayout* geomLayout;
|
||||
std::array<int, REG_COUNT> regMapping;
|
||||
|
||||
struct vertex_buffer_slot{
|
||||
Buffer* buffer;
|
||||
size_t stride;
|
||||
};
|
||||
|
||||
std::array<vertex_buffer_slot, 8> vbSlots;
|
||||
std::array<Buffer*, 8> ibSlots;
|
||||
VertexShader* vs;
|
||||
PixelShader* ps;
|
||||
int primitiveType;
|
||||
|
||||
Texture* backBuffer;
|
||||
Texture* depthBuffer;
|
||||
};
|
||||
#endif // BlockRasterizer_h__
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
#ifndef Buffer_h__
|
||||
#define Buffer_h__
|
||||
|
||||
#include <string.h>
|
||||
#include <cstdint>
|
||||
#include "Debug.h"
|
||||
|
||||
class Buffer {
|
||||
public:
|
||||
constexpr Buffer()
|
||||
{
|
||||
|
||||
}
|
||||
virtual ~Buffer() = default;
|
||||
void Write(void* src, size_t offset, size_t length){
|
||||
SGL_ASSERT(src != nullptr, "Invalid pointer");
|
||||
SGL_ASSERT((offset + length) <= Size(), "Invalid pointer");
|
||||
|
||||
memcpy((uint8_t*)GetPointer() + offset, src, length);
|
||||
}
|
||||
void Read(void* dst, size_t offset, int length){
|
||||
memcpy(dst, (uint8_t*)GetPointer() + offset, length);
|
||||
}
|
||||
virtual void* GetPointer() = 0;
|
||||
virtual size_t Size() = 0;
|
||||
virtual size_t ItemSize()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
#endif // Buffer_h__
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
#ifndef Debug_h__
|
||||
#define Debug_h__
|
||||
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
|
||||
#if defined(DEBUG) || defined(_DEBUG)
|
||||
#define SGL_DEBUG
|
||||
#define SGL_ASSERT(__expr, __text) assert(__expr && __text);
|
||||
#else
|
||||
#define SGL_ASSERT(__expr, __text)
|
||||
#endif
|
||||
|
||||
#define DebugInfo(...) printf("Info: "); printf(__VA_ARGS__); printf("\n");
|
||||
#define DebugError(...) printf("Error: "); printf(__VA_ARGS__); printf("\n");
|
||||
|
||||
#endif // Debug_h__
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
#ifndef DisplayMode_h__
|
||||
#define DisplayMode_h__
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
struct DisplayMode {
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t refreshRate;
|
||||
uint32_t bpp;
|
||||
};
|
||||
|
||||
#endif // DisplayMode_h__
|
||||
@@ -0,0 +1,69 @@
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
|
||||
|
||||
template<size_t AveragingFramesCount = 20>
|
||||
class FpsCounter
|
||||
{
|
||||
public:
|
||||
|
||||
using Clock = std::chrono::steady_clock;
|
||||
using Duration = std::chrono::steady_clock::duration;
|
||||
using TimePoint = std::chrono::steady_clock::time_point;
|
||||
|
||||
FpsCounter():position(0),avgFps(0) {
|
||||
_lastClock = Clock::now();
|
||||
timeElapsed = timeElapsed.zero();
|
||||
for (size_t i = 0; i < AveragingFramesCount; ++i) {
|
||||
_buffer[i] = {};
|
||||
}
|
||||
}
|
||||
~FpsCounter()
|
||||
{
|
||||
|
||||
}
|
||||
void ComputeFPS(){
|
||||
auto nowTime = Clock::now();
|
||||
timeElapsed = nowTime - _lastClock;
|
||||
_lastClock = nowTime;
|
||||
|
||||
_buffer[position] = timeElapsed;
|
||||
position = (position + 1) % AveragingFramesCount;
|
||||
|
||||
Duration sum = {};
|
||||
for (size_t i = 0; i < AveragingFramesCount; ++i) {
|
||||
sum += _buffer[i];
|
||||
}
|
||||
|
||||
auto us = std::chrono::duration_cast<std::chrono::microseconds>(sum).count() / AveragingFramesCount;
|
||||
if (us == 0) {
|
||||
avgFps = 0.0f;
|
||||
} else {
|
||||
avgFps =1.0f / ( (float)us / 1000000.0f);
|
||||
}
|
||||
}
|
||||
float PreciseFPS() {
|
||||
float time = GetFrameTimeSeconds();
|
||||
if (time <= 0.0f) {
|
||||
return 0.0f;
|
||||
}
|
||||
return 1.0f / time;
|
||||
}
|
||||
float AverageFPS()
|
||||
{
|
||||
return avgFps;
|
||||
}
|
||||
float GetFrameTimeSeconds() const {
|
||||
return (float)std::chrono::duration_cast<std::chrono::microseconds>(timeElapsed).count() / 1000000.0f;
|
||||
}
|
||||
Duration GetTimeElapsed() const {
|
||||
return timeElapsed;
|
||||
}
|
||||
private:
|
||||
TimePoint _lastClock;
|
||||
Duration timeElapsed;
|
||||
float avgFps;
|
||||
Duration _buffer[AveragingFramesCount];
|
||||
int position;
|
||||
};
|
||||
@@ -0,0 +1,66 @@
|
||||
#pragma once
|
||||
|
||||
#include <SoftGL/PixelShader.h>
|
||||
#include <SoftGL/BRDF/lighting_core.h>
|
||||
|
||||
class PsNormalMap : public PixelShader {
|
||||
public:
|
||||
float3 camPosition;
|
||||
float4 diffuse;
|
||||
Texture* diffuse_map;
|
||||
Texture* normal_map;
|
||||
Texture* ao_map;
|
||||
float ior = 1.5f;
|
||||
float M = 0.7f;
|
||||
|
||||
PsNormalMap() :diffuse_map(nullptr), normal_map(nullptr), diffuse(0) {
|
||||
|
||||
}
|
||||
float4 Execute(float4* input) {
|
||||
//return float4(1, 1, 0, 1);
|
||||
//return float4(input[1].x, input[1].y, 0, 1);
|
||||
|
||||
float3 lightColor = float3(1.0f, 1.0f, 0.9f);
|
||||
|
||||
float3 ambientColor = float3(0.1f, 0.1f, 0.25f);
|
||||
|
||||
float4 normal_tbn = tex2D(normal_map, input[1].x(), input[1].y(), TextureFilter::Bilinear);
|
||||
auto tmp = normal_tbn.y();
|
||||
normal_tbn.y() = normal_tbn.z();
|
||||
normal_tbn.z() = tmp;
|
||||
|
||||
float4 ao = tex2D(ao_map, input[1].x(), input[1].y(), TextureFilter::Bilinear);
|
||||
|
||||
//return float4(normal_tbn.x, normal_tbn.y, normal_tbn.z, 1);
|
||||
|
||||
float3 N = lm::normalize(normal_tbn.xyz() * 2.0f - 1.0f); //lm::normalize(input[2].xyz);
|
||||
|
||||
float3 L = lm::normalize(float3(1, 1, 1));
|
||||
float3 V = lm::normalize(camPosition - input[3].xyz());
|
||||
float3 H = normalize(L + V);
|
||||
|
||||
float NdotL = std::max<float>(0, lm::dot(N, L));
|
||||
float NdotV = std::max<float>(0, lm::dot(N, V));
|
||||
float LdotH = lm::dot(L, H);
|
||||
|
||||
float F = Fresnel(LdotH, ior);
|
||||
|
||||
float G = G_Cook_Torrance(N, H, V, L);
|
||||
|
||||
float D = D_Beckmann(H, N, M);
|
||||
|
||||
float r_microfacet = (F * G * D) / (4 * NdotL * NdotV + 1.0e-7) * MATH_PI* NdotL;
|
||||
|
||||
float4 diffuse = tex2D(diffuse_map, input[1].x(), input[1].y(), TextureFilter::Bilinear);
|
||||
|
||||
float3 result = float3(0, 0, 0);
|
||||
result = diffuse.xyz() * (lightColor * diffuse.xyz()) * NdotL + lightColor * r_microfacet + ambientColor * diffuse.xyz() * ao.x();
|
||||
|
||||
result = lm::saturate(result);
|
||||
|
||||
float4 retval;
|
||||
retval.xyz() = result;
|
||||
retval.w() = diffuse.w();
|
||||
return retval;
|
||||
}
|
||||
};
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
#pragma once
|
||||
|
||||
#include <LMath/lmath.h>
|
||||
#include "gameobject.h"
|
||||
|
||||
class Camera {
|
||||
public:
|
||||
Camera(Game_object* object):
|
||||
_fov(3.1415f/4.0f), _zNear(0.3f), _zFar(100.0f), _aspect(1.0f), _object(object){
|
||||
UpdateProjection();
|
||||
}
|
||||
|
||||
lm::float4x4 world_to_camera_matrix(){
|
||||
auto tf = _object->transform.get_global_transform();
|
||||
return lm::inverse(tf, false);
|
||||
}
|
||||
Game_object* GameObject()
|
||||
{
|
||||
return _object;
|
||||
}
|
||||
float4x4 GetProjection() const{
|
||||
return _projection;
|
||||
}
|
||||
float GetFov() const{
|
||||
return _fov;
|
||||
}
|
||||
void SetFov(float fov) {
|
||||
_fov = fov;
|
||||
UpdateProjection();
|
||||
}
|
||||
float GetAspect() const {
|
||||
return _aspect;
|
||||
}
|
||||
void SetAspect(float aspect) {
|
||||
_aspect = aspect;
|
||||
UpdateProjection();
|
||||
}
|
||||
float GetZNear() const {
|
||||
return _zNear;
|
||||
}
|
||||
void SetZNear(float zNear) {
|
||||
_zNear = zNear;
|
||||
UpdateProjection();
|
||||
}
|
||||
float GetZFar() const {
|
||||
return _zFar;
|
||||
}
|
||||
void SetZFar(float zFar) {
|
||||
_zFar = zFar;
|
||||
UpdateProjection();
|
||||
}
|
||||
private:
|
||||
void UpdateProjection(){
|
||||
_projection = lm::matrix4x4Perspective(_fov, _aspect, _zNear, _zFar);
|
||||
}
|
||||
float _fov;
|
||||
float _zNear;
|
||||
float _zFar;
|
||||
float _aspect;
|
||||
float4x4 _projection;
|
||||
Game_object* _object;
|
||||
};
|
||||
@@ -0,0 +1,53 @@
|
||||
#pragma once
|
||||
|
||||
#include "camera.h"
|
||||
#include <LFramework/Input/Input.h>
|
||||
#include <LMath/lmath.h>
|
||||
|
||||
class CameraController{
|
||||
public:
|
||||
float mouse_speed;
|
||||
float move_speed = 3.0f;
|
||||
static constexpr float pi = 3.14159265358979f;
|
||||
|
||||
CameraController(Camera* camera) : mouse_speed(0.01f), _camera(camera) {
|
||||
_angle_x = _angle_y = 0.0f;
|
||||
}
|
||||
|
||||
void Tick(float deltaTime) {
|
||||
auto mice = Input::Instance()->mice();
|
||||
auto mouse = mice[1];
|
||||
|
||||
if(mouse->GetKeyState(1)){
|
||||
_angle_x += mouse_speed * mouse->GetDx();
|
||||
_angle_y += mouse_speed * mouse->GetDy();
|
||||
_angle_y = clamp(_angle_y, -pi / 2.0f, pi / 2.0f);
|
||||
auto rv = lm::Quaternion_f::angleAxis(_angle_y, lm::float3(1, 0, 0));
|
||||
auto rh = lm::Quaternion_f::angleAxis(_angle_x, lm::float3(0, 1, 0));
|
||||
_camera->GameObject()->transform.set_local_rotation(lm::mul(rh, rv));
|
||||
}
|
||||
|
||||
auto keyboard = Input::Instance()->keyboards()[3];
|
||||
auto& tf = _camera->GameObject()->transform;
|
||||
|
||||
if (keyboard->GetKeyState(0x57)) {
|
||||
tf.SetLocalPosition(tf.GetLocalPosition() + tf.Forward() * (deltaTime * move_speed));
|
||||
}
|
||||
|
||||
if (keyboard->GetKeyState(0x53)) {
|
||||
tf.SetLocalPosition(tf.GetLocalPosition() - tf.Forward() * (deltaTime * move_speed));
|
||||
}
|
||||
|
||||
if (keyboard->GetKeyState(0x41)) {
|
||||
tf.SetLocalPosition(tf.GetLocalPosition() - tf.right() * (deltaTime * move_speed));
|
||||
}
|
||||
|
||||
if (keyboard->GetKeyState(0x44)) {
|
||||
tf.SetLocalPosition(tf.GetLocalPosition() + tf.right() * (deltaTime * move_speed));
|
||||
}
|
||||
}
|
||||
private:
|
||||
Camera* _camera;
|
||||
float _angle_x;
|
||||
float _angle_y;
|
||||
};
|
||||
@@ -0,0 +1,91 @@
|
||||
#pragma once
|
||||
|
||||
#include "imesh.h"
|
||||
#include <LMath/lmath.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace lm;
|
||||
|
||||
template<typename TVertex, typename TIndex>
|
||||
struct CubeGenerator {
|
||||
static constexpr size_t VertexCount = 24;
|
||||
static constexpr size_t IndexCount = 36;
|
||||
|
||||
static constexpr float4 Corner(size_t id) {
|
||||
return float4(id % 2 == 0 ? -1.0f : 1.0f, id < 4 ? 1.0f : -1.0f, (id % 4) < 2 ? 1.0f : -1.0f, 1.0f);
|
||||
}
|
||||
|
||||
static bool Generate(IMesh* m) {
|
||||
if (m == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto vb = m->GetVertexBuffer();
|
||||
if (vb == nullptr || (vb->Size() / vb->ItemSize()) < VertexCount) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto ib = m->GetSubmeshBuffer(0);
|
||||
if (ib == nullptr || (ib->Size() / ib->ItemSize()) < IndexCount) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static constexpr float extent = 0.5f;
|
||||
|
||||
|
||||
// 0-1
|
||||
//2-3
|
||||
//
|
||||
// 4-5
|
||||
//6-7
|
||||
|
||||
static constexpr std::array<size_t, 4> sides[6] = {
|
||||
{ 3,1,5,7 },
|
||||
{ 0,2,6,4 },
|
||||
{ 0,1,3,2 },
|
||||
{ 6,7,5,4 },
|
||||
{ 1,0,4,5 },
|
||||
{ 2,3,7,6 }
|
||||
};
|
||||
|
||||
static constexpr std::array<float3, 6> normals = {
|
||||
float3(1.0f,0.0f,0.0f),
|
||||
float3(-1.0f,0.0f,0.0f),
|
||||
float3(0.0f,1.0f,0.0f),
|
||||
float3(0.0f,-1.0f,0.0f),
|
||||
float3(0.0f,0.0f,1.0f),
|
||||
float3(0.0f,0.0f,-1.0f)
|
||||
};
|
||||
|
||||
static constexpr float2 uvs[4] = {
|
||||
float2(0.0f,0.0f),
|
||||
float2(1.0f,0.0f),
|
||||
float2(1.0f,1.0f),
|
||||
float2(0.0f,1.0f)
|
||||
};
|
||||
|
||||
static constexpr size_t indexMap[6] = {
|
||||
0,1,3,3,1,2
|
||||
};
|
||||
|
||||
auto vertices = (TVertex*)vb->GetPointer();
|
||||
auto indices = (TIndex*)ib->GetPointer();
|
||||
|
||||
for(size_t i = 0; i < 6; ++i){
|
||||
//update vertices
|
||||
for (size_t j = 0; j < 4; ++j) {
|
||||
auto& vertex = vertices[i * 4 + j];
|
||||
vertex.Position = Corner(sides[i][j]);
|
||||
vertex.Normal = normals[i];
|
||||
vertex.UV0 = uvs[j];
|
||||
}
|
||||
auto indexBase = i * 4;
|
||||
for (size_t j = 0; j < 6; ++j) {
|
||||
indices[i * 6 + j] = indexBase + indexMap[j];
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
#ifndef fresnel_h__
|
||||
#define fresnel_h__
|
||||
|
||||
#include <cmath>
|
||||
|
||||
inline float Fresnel(float c, float ior) {
|
||||
float g = std::sqrt(ior*ior + c*c - 1);
|
||||
return 0.5f * std::pow(g - c, 2) / std::pow(g + c, 2) * (1 + std::pow(c*(g + c) - 1, 2) / std::pow(c*(g - c) + 1, 2));
|
||||
}
|
||||
#endif // fresnel_h__
|
||||
@@ -0,0 +1,14 @@
|
||||
#ifndef gameobject_h__
|
||||
#define gameobject_h__
|
||||
|
||||
#include "transform.h"
|
||||
|
||||
class Game_object {
|
||||
public:
|
||||
Transform transform;
|
||||
Game_object():transform(this)
|
||||
{
|
||||
|
||||
}
|
||||
};
|
||||
#endif // gameobject_h__
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <SoftGL/Buffer.h>
|
||||
#include <SoftGL/static_vector.h>
|
||||
|
||||
class IMesh {
|
||||
public:
|
||||
virtual Buffer* GetVertexBuffer() = 0;
|
||||
virtual size_t GetSubmeshCount() const = 0;
|
||||
virtual Buffer* GetSubmeshBuffer(size_t id) const = 0;
|
||||
};
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
#ifndef mesh_h__
|
||||
#define mesh_h__
|
||||
|
||||
#include "imesh.h"
|
||||
#include <array>
|
||||
|
||||
template<size_t SubmeshCount>
|
||||
class Mesh : public IMesh {
|
||||
public:
|
||||
Buffer* vertexBuffer;
|
||||
std::array<Buffer*, SubmeshCount> submeshes;
|
||||
|
||||
virtual Buffer* GetVertexBuffer() override {
|
||||
return vertexBuffer;
|
||||
}
|
||||
|
||||
virtual size_t GetSubmeshCount() const override {
|
||||
return SubmeshCount;
|
||||
}
|
||||
|
||||
virtual Buffer* GetSubmeshBuffer(size_t id) const override {
|
||||
return submeshes[id];
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // mesh_h__
|
||||
@@ -0,0 +1,70 @@
|
||||
#pragma once
|
||||
|
||||
#include "imesh.h"
|
||||
#include <LMath/lmath.h>
|
||||
|
||||
using namespace lm;
|
||||
|
||||
template<typename TVertex, typename TIndex>
|
||||
struct PlaneGenerator {
|
||||
static constexpr size_t VertexCount = 4;
|
||||
static constexpr size_t IndexCount = 6;
|
||||
|
||||
static constexpr float4 Corner(size_t id) {
|
||||
return float4(id % 2 == 0 ? -1.0f : 1.0f, 0.0f, (id % 4) < 2 ? 1.0f : -1.0f, 1.0f);
|
||||
}
|
||||
|
||||
static bool Generate(IMesh* m) {
|
||||
if (m == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto vb = m->GetVertexBuffer();
|
||||
if (vb == nullptr || (vb->Size() / vb->ItemSize()) < VertexCount) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto ib = m->GetSubmeshBuffer(0);
|
||||
if (ib == nullptr || (ib->Size() / ib->ItemSize()) < IndexCount) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static constexpr std::array<float3, 6> normals = {
|
||||
float3(1.0f,0.0f,0.0f),
|
||||
float3(-1.0f,0.0f,0.0f),
|
||||
float3(0.0f,1.0f,0.0f),
|
||||
float3(0.0f,-1.0f,0.0f),
|
||||
float3(0.0f,0.0f,1.0f),
|
||||
float3(0.0f,0.0f,-1.0f)
|
||||
};
|
||||
|
||||
static constexpr float2 uvs[4] = {
|
||||
float2(0.0f, 0.0f),
|
||||
float2(1.0f, 0.0f),
|
||||
float2(0.0f, 1.0f),
|
||||
float2(1.0f, 1.0f)
|
||||
};
|
||||
|
||||
static constexpr size_t planeIndices[6] = {
|
||||
0,1,2,2,1,3
|
||||
};
|
||||
|
||||
auto vertices = (TVertex*)vb->GetPointer();
|
||||
auto indices = (TIndex*)ib->GetPointer();
|
||||
|
||||
//update vertices
|
||||
for (size_t j = 0; j < 4; ++j) {
|
||||
auto& vertex = vertices[j];
|
||||
vertex.Position = Corner(j);
|
||||
vertex.Normal = float3(0.0f, 1.0f, 0.0f);
|
||||
vertex.UV0 = uvs[j];
|
||||
}
|
||||
|
||||
for (size_t j = 0; j < 6; ++j) {
|
||||
indices[j] = planeIndices[j];
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <SoftGL/PixelShader.h>
|
||||
|
||||
class PSTexturedNoLit : public PixelShader {
|
||||
public:
|
||||
Texture* diffuseMap;
|
||||
|
||||
PSTexturedNoLit() :diffuseMap(nullptr) {}
|
||||
|
||||
float4 Execute(float4* input) {
|
||||
float4 diffuse = float4(0, 0, 0, 0);
|
||||
if (diffuseMap != nullptr) {
|
||||
diffuse = tex2D(diffuseMap, input[1].x(), input[1].y(), TextureFilter::Bilinear);
|
||||
}
|
||||
return diffuse;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,84 @@
|
||||
#pragma once
|
||||
|
||||
#include <LMath/lmath.h>
|
||||
|
||||
using namespace lm;
|
||||
|
||||
class Game_object;
|
||||
|
||||
class Transform {
|
||||
public:
|
||||
Transform* parent;
|
||||
lm::Quaternion_f _rotation;
|
||||
float3 _position;
|
||||
float3 _scale;
|
||||
|
||||
Transform(Game_object* game_object)
|
||||
:parent(nullptr), _scale(1, 1, 1), _position(0, 0, 0), _rotation(0, 0, 0, 1), _game_object(game_object) {
|
||||
|
||||
}
|
||||
|
||||
std::wstring class_name() const {
|
||||
return L"Transform";
|
||||
}
|
||||
|
||||
void SetLocalPosition(const float3& position) {
|
||||
_position = position;
|
||||
}
|
||||
float3 GetLocalPosition() {
|
||||
return _position;
|
||||
}
|
||||
|
||||
float3 Forward() const {
|
||||
return get_global_transform()[2].xyz();
|
||||
}
|
||||
|
||||
float3 right() const {
|
||||
return get_global_transform()[0].xyz();
|
||||
}
|
||||
|
||||
float3 up() const {
|
||||
return get_global_transform()[1].xyz();
|
||||
}
|
||||
|
||||
void set_local_rotation(const Quaternion_f& rotation) {
|
||||
_rotation = rotation;
|
||||
}
|
||||
|
||||
Quaternion_f get_local_rotation() {
|
||||
return _rotation;
|
||||
}
|
||||
|
||||
void set_local_scale(const float3& scale) {
|
||||
_scale = scale;
|
||||
}
|
||||
|
||||
float3 get_local_scale() {
|
||||
return _scale;
|
||||
}
|
||||
|
||||
float4x4 get_local_transform() const {
|
||||
float4x4 scaleMatrix = matrix4x4Scale(_scale);
|
||||
float4x4 rotationMatrix = matrix4x4RotationQuaternion(_rotation);
|
||||
float4x4 positionMatrix = matrix4x4Translation(_position);
|
||||
return lm::mul(lm::mul(scaleMatrix, rotationMatrix), positionMatrix);
|
||||
}
|
||||
|
||||
float4x4 get_global_transform() const {
|
||||
if (parent == nullptr) {
|
||||
return get_local_transform();
|
||||
}
|
||||
return lm::mul(get_local_transform(), parent->get_global_transform());
|
||||
}
|
||||
|
||||
float3 get_global_position() {
|
||||
auto tf = get_global_transform();
|
||||
return float3(tf[3][0], tf[3][1], tf[3][2]);
|
||||
}
|
||||
|
||||
void RotateLocal(const Quaternion_f& rotation) {
|
||||
_rotation = lm::mul(_rotation, rotation);
|
||||
}
|
||||
private:
|
||||
Game_object* _game_object;
|
||||
};
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
#ifndef Graphics2D_h__
|
||||
#define Graphics2D_h__
|
||||
|
||||
#include "Texture.h"
|
||||
|
||||
|
||||
struct TextureWriter {
|
||||
Texture* texture;
|
||||
|
||||
size_t width() {
|
||||
return texture->Desc().Width;
|
||||
}
|
||||
size_t height() {
|
||||
return texture->Desc().Height;
|
||||
}
|
||||
template<typename Color>
|
||||
void setPixel(int32_t x, int32_t y, Color color) {
|
||||
if (x < 0 || y < 0) {
|
||||
return;
|
||||
}
|
||||
if (x >= (int64_t)width() || y >= (int64_t)height()) {
|
||||
return;
|
||||
}
|
||||
uint8_t* data = ((uint8_t*)texture->LockWrite()) + (y * width() + x) * sizeof(color);
|
||||
memcpy(data, &color, sizeof(color));
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
template<typename PixelWriter, typename Color>
|
||||
void clear(PixelWriter& writer, const Color& color) {
|
||||
for (size_t y = 0; y < writer.height(); ++y) {
|
||||
for (size_t x = 0; x < writer.width(); ++x) {
|
||||
writer.setPixel(x, y, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename PixelWriter, typename Color>
|
||||
void drawCircle(int X1, int Y1, int R, PixelWriter& writer, const Color& color) {
|
||||
int x = 0;
|
||||
int y = R;
|
||||
int delta = 1 - 2 * R;
|
||||
int error = 0;
|
||||
while (y >= 0) {
|
||||
writer.setPixel(X1 + x, Y1 + y, color);
|
||||
writer.setPixel(X1 + x, Y1 - y, color);
|
||||
writer.setPixel(X1 - x, Y1 + y, color);
|
||||
writer.setPixel(X1 - x, Y1 - y, color);
|
||||
error = 2 * (delta + y) - 1;
|
||||
if ((delta < 0) && (error <= 0)) {
|
||||
delta += 2 * ++x + 1;
|
||||
continue;
|
||||
}
|
||||
error = 2 * (delta - x) - 1;
|
||||
if ((delta > 0) && (error > 0)) {
|
||||
delta += 1 - 2 * --y;
|
||||
continue;
|
||||
}
|
||||
x++;
|
||||
delta += 2 * (x - y);
|
||||
y--;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename PixelWriter, typename Color>
|
||||
void drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, PixelWriter& writer, const Color& color) {
|
||||
int32_t steep = abs(y1 - y0) > abs(x1 - x0);
|
||||
if (steep) {
|
||||
std::swap(x0, y0);
|
||||
std::swap(x1, y1);
|
||||
}
|
||||
|
||||
if (x0 > x1) {
|
||||
std::swap(x0, x1);
|
||||
std::swap(y0, y1);
|
||||
}
|
||||
|
||||
int32_t dx = x1 - x0;
|
||||
int32_t dy = abs(y1 - y0);
|
||||
|
||||
auto err = dx / 2;
|
||||
int32_t ystep;
|
||||
|
||||
if (y0 < y1) {
|
||||
ystep = 1;
|
||||
}
|
||||
else {
|
||||
ystep = -1;
|
||||
}
|
||||
|
||||
for (; x0 <= x1; x0++) {
|
||||
if (steep) {
|
||||
writer.setPixel(y0, x0, color);
|
||||
}
|
||||
else {
|
||||
writer.setPixel(x0, y0, color);
|
||||
}
|
||||
err -= dy;
|
||||
if (err < 0) {
|
||||
y0 += ystep;
|
||||
err += dx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif // Graphics2D_h__
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
#pragma once
|
||||
|
||||
#include "LString.h"
|
||||
#include "DisplayMode.h"
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include "Texture.h"
|
||||
|
||||
class IRenderWindow{
|
||||
public:
|
||||
virtual ~IRenderWindow(void) {}
|
||||
virtual void Update() = 0;
|
||||
virtual void SetCaption(const String& caption) = 0;
|
||||
virtual std::size_t GetWindowHandle() = 0;
|
||||
virtual int GetWidth() = 0;
|
||||
virtual int GetHeight() = 0;
|
||||
virtual int GetTop() = 0;
|
||||
virtual int GetLeft() = 0;
|
||||
virtual void SetPosition(int top, int left) = 0;
|
||||
virtual void SetSize(int w, int h) = 0;
|
||||
virtual const String& GetCaption() = 0;
|
||||
|
||||
virtual bool IsFullScreen() = 0;
|
||||
virtual void SetFullScreen(bool state) = 0;
|
||||
virtual bool SwitchMode(bool fullscreen) = 0;
|
||||
virtual void SetFullscreenMode(DisplayMode mode) = 0;
|
||||
|
||||
virtual const DisplayMode& GetFullscreenMode()
|
||||
{
|
||||
return fsMode;
|
||||
}
|
||||
virtual void Present(Texture* tex) = 0;
|
||||
|
||||
virtual void OnActivate() = 0;
|
||||
virtual void OnDeactivate() = 0;
|
||||
virtual void OnResize() = 0;
|
||||
virtual bool IsActive() = 0;
|
||||
virtual bool IsModeSwitching() = 0;
|
||||
virtual void SetCursorVisible(bool state) = 0;
|
||||
virtual bool IsCursorVisible() = 0;
|
||||
virtual void CenterWindow() = 0;
|
||||
protected:
|
||||
bool bCursorVisible;
|
||||
bool bModeSwitching;
|
||||
bool bFullscreen;
|
||||
bool bActive;
|
||||
int width;
|
||||
int height;
|
||||
String caption;
|
||||
DisplayMode fsMode;
|
||||
};
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
#ifndef IShader_h__
|
||||
#define IShader_h__
|
||||
|
||||
#include "LString.h"
|
||||
#include <vector>
|
||||
#include <LMath/lmath.h>
|
||||
|
||||
using namespace lm;
|
||||
using namespace std;
|
||||
|
||||
class IShader
|
||||
{
|
||||
protected:
|
||||
typedef std::vector<String> RegisterList;
|
||||
RegisterList inputs;
|
||||
|
||||
public:
|
||||
int RegisterCount()
|
||||
{
|
||||
return inputs.size();
|
||||
}
|
||||
int FindRegister(const String& name)
|
||||
{
|
||||
int cnt = inputs.size();
|
||||
if(!cnt) return -1;
|
||||
|
||||
RegisterList::iterator it = inputs.begin();
|
||||
for(int i = 0; i < cnt; i++)
|
||||
{
|
||||
if((*it) == name) return i;
|
||||
it++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
IShader()
|
||||
{
|
||||
|
||||
}
|
||||
virtual ~IShader()
|
||||
{
|
||||
|
||||
}
|
||||
};
|
||||
#endif // IShader_h__
|
||||
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include <LMath/lmath.h>
|
||||
#include <cstdint>
|
||||
|
||||
class ImageDataAccessorR5G6B5 {
|
||||
public:
|
||||
|
||||
using PixelDataType = std::uint16_t;
|
||||
static constexpr bool HasAlpha = true;
|
||||
|
||||
static PixelDataType ConvertColor(const lm::float4& color) {
|
||||
PixelDataType r = (uint32_t)(color.x() * 0x1f);
|
||||
PixelDataType g = (uint32_t)(color.y() * 0x3f);
|
||||
PixelDataType b = (uint32_t)(color.z() * 0x1f);
|
||||
|
||||
return (r << 11) | (g << 5) | (b);
|
||||
}
|
||||
|
||||
static lm::float4 ConvertColor(PixelDataType color) {
|
||||
float r = (float)(color >> 11) / 0x1f;
|
||||
float g = (float)((color >> 5) & 0x3f) / 0x3f;
|
||||
float b = (float)((color >> 0) & 0x1f) / 0x1f;
|
||||
return lm::float4(r, g, b, 1.0f);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,31 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LMath/lmath.h>
|
||||
#include <cstdint>
|
||||
|
||||
class ImageDataAccessorR8G8B8 {
|
||||
public:
|
||||
|
||||
using PixelDataType = std::uint32_t;
|
||||
static constexpr bool HasAlpha = true;
|
||||
|
||||
static uint32_t ConvertColor(const lm::float4& color) {
|
||||
uint32_t r = (uint32_t)(color.x() * 255.0f);
|
||||
uint32_t g = (uint32_t)(color.y() * 255.0f);
|
||||
uint32_t b = (uint32_t)(color.z() * 255.0f);
|
||||
uint32_t a = (uint32_t)(color.w() * 255.0f);
|
||||
|
||||
return (a << 24) | (r << 16) | (g << 8) | (b);
|
||||
}
|
||||
|
||||
static lm::float4 ConvertColor(uint32_t color) {
|
||||
float d = 1.0f / 255.0f;
|
||||
|
||||
float a = (float)((color >> 24) & 0xff) * d;
|
||||
float r = (float)((color >> 16) & 0xff) * d;
|
||||
float g = (float)((color >> 8) & 0xff) * d;
|
||||
float b = (float)((color >> 0) & 0xff) * d;
|
||||
return lm::float4(r, g, b, a);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,6 @@
|
||||
#ifndef IndexBuffer_h__
|
||||
#define IndexBuffer_h__
|
||||
|
||||
|
||||
|
||||
#endif // IndexBuffer_h__
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
#ifndef InputLayout_h__
|
||||
#define InputLayout_h__
|
||||
|
||||
#include "LString.h"
|
||||
#include "RasterizerSettings.h"
|
||||
#include "Debug.h"
|
||||
#include <array>
|
||||
|
||||
enum class RegType {
|
||||
float1 = 0,
|
||||
float2 = 1,
|
||||
float3 = 2,
|
||||
float4 = 3
|
||||
};
|
||||
|
||||
struct InputElement {
|
||||
char name[InputElementNameLength];
|
||||
uint8_t Offset;
|
||||
RegType type;
|
||||
uint8_t StreamId;
|
||||
|
||||
InputElement() :name{0}, Offset(0), type(RegType::float1), StreamId(0){
|
||||
|
||||
}
|
||||
InputElement(const char* _name, uint8_t offset, RegType t, uint8_t stream) {
|
||||
SGL_ASSERT(strlen(_name) < InputElementNameLength, "Too long name for InputElement");
|
||||
strcpy(name, _name);
|
||||
Offset = offset;
|
||||
type = t;
|
||||
StreamId = stream;
|
||||
}
|
||||
};
|
||||
|
||||
class IInputLayout {
|
||||
public:
|
||||
virtual size_t Size() = 0;
|
||||
virtual InputElement* GetElement(size_t id) = 0;
|
||||
int FindElement(const char* name) {
|
||||
auto size = Size();
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
if (strcmp(GetElement(i)->name, name) == 0)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
|
||||
template<size_t _Size>
|
||||
class StaticInputLayout : public IInputLayout {
|
||||
public:
|
||||
std::array<InputElement, _Size> elements;
|
||||
virtual size_t Size() override {
|
||||
return _Size;
|
||||
}
|
||||
virtual InputElement* GetElement(size_t id) override {
|
||||
return &elements[id];
|
||||
}
|
||||
};
|
||||
#endif // InputLayout_h__
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
#ifndef InputSystem_h__
|
||||
#define InputSystem_h__
|
||||
|
||||
#include <OIS.h>
|
||||
#include <sstream>
|
||||
#include "RenderWindow.h"
|
||||
#include "Delegate.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
#pragma comment (lib, "OIS_static_d.lib")
|
||||
#else
|
||||
#pragma comment (lib, "OIS_static.lib")
|
||||
#endif
|
||||
|
||||
using namespace OIS;
|
||||
|
||||
class InputSystem : public OIS::KeyListener, public OIS::MouseListener
|
||||
{
|
||||
public:
|
||||
EVENT1(KBEvent, int);
|
||||
KBEvent Event_KeyDown;
|
||||
KBEvent Event_KeyUp;
|
||||
|
||||
EVENT4(MSEvent, int, int, int, int);
|
||||
MSEvent Event_MouseMove;
|
||||
|
||||
InputSystem(RenderWindow* window, int sw, int sh)
|
||||
{
|
||||
//init Input
|
||||
ParamList pl;
|
||||
|
||||
HWND hw = (HWND)window->GetWindowHandle();
|
||||
std::ostringstream wnd;
|
||||
wnd << (size_t)hw;
|
||||
pl.insert(std::make_pair( std::string("WINDOW"), wnd.str() ));
|
||||
|
||||
bool hideCursor = false;
|
||||
|
||||
if( !hideCursor)
|
||||
{
|
||||
pl.insert(std::make_pair(std::string("w32_mouse") , std::string("DISCL_BACKGROUND" )));
|
||||
|
||||
pl.insert(std::make_pair(std::string("w32_mouse") , std::string("DISCL_NONEXCLUSIVE")));
|
||||
}
|
||||
pl.insert(std::make_pair(std::string("w32_keyboard"), std::string("DISCL_BACKGROUND")));
|
||||
|
||||
pl.insert(std::make_pair(std::string("w32_keyboard"), std::string ("DISCL_NONEXCLUSIVE") ));
|
||||
|
||||
|
||||
|
||||
|
||||
input = InputManager::createInputSystem(pl);
|
||||
keyboard = (Keyboard*)input->createInputObject(OISKeyboard,1);
|
||||
mouse = (Mouse*)input->createInputObject(OISMouse,1);
|
||||
mouse->getMouseState().width = sw;
|
||||
mouse->getMouseState().height = sh;
|
||||
|
||||
keyboard->setEventCallback(this);
|
||||
mouse->setEventCallback(this);
|
||||
}
|
||||
~InputSystem()
|
||||
{
|
||||
input->destroyInputObject(mouse);
|
||||
input->destroyInputObject(keyboard);
|
||||
InputManager::destroyInputSystem(input);
|
||||
}
|
||||
void Capture()
|
||||
{
|
||||
mouse->capture();
|
||||
keyboard->capture();
|
||||
}
|
||||
|
||||
bool keyPressed(const KeyEvent &arg)
|
||||
{
|
||||
Event_KeyDown.Invoke((int)arg.key);
|
||||
return true;
|
||||
}
|
||||
bool keyReleased(const KeyEvent &arg)
|
||||
{
|
||||
Event_KeyUp.Invoke((int)arg.key);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mouseMoved( const MouseEvent &arg )
|
||||
{
|
||||
Event_MouseMove.Invoke(arg.state.X.abs, arg.state.Y.abs, arg.state.X.rel, arg.state.Y.rel);
|
||||
return true;
|
||||
}
|
||||
bool mousePressed( const MouseEvent &arg, MouseButtonID id )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool mouseReleased( const MouseEvent &arg, MouseButtonID id )
|
||||
{
|
||||
|
||||
return true;
|
||||
}
|
||||
void SetKeyDownCallback()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
InputManager* input;
|
||||
Keyboard* keyboard;
|
||||
Mouse* mouse;
|
||||
|
||||
};
|
||||
#endif // InputSystem_h__
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
#ifndef LSTRING_H__
|
||||
#define LSTRING_H__
|
||||
#include <string>
|
||||
|
||||
#ifdef _UNICODE
|
||||
#define _text(str) L##str
|
||||
typedef std::wstring String;
|
||||
#define PRINT wprintf
|
||||
#define STRCMP wcscmp
|
||||
typedef wchar_t tchar;
|
||||
#define string_size(str) (str.length() * 2)
|
||||
#else
|
||||
#define _text(str) str
|
||||
#define PRINT printf
|
||||
typedef std::string String;
|
||||
typedef char tchar;
|
||||
#define STRCMP strcmp
|
||||
#define string_size(str) (str.length())
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#define PATH_SPLITTER _text("\\")
|
||||
#else
|
||||
#define PATH_SPLITTER _text("/")
|
||||
#endif
|
||||
|
||||
extern String GetFileName(const String& path);
|
||||
|
||||
extern String GetFileName(const String& path, const String& pathSplitter);
|
||||
|
||||
extern String GetFileNameWithoutExtention(const String& path);
|
||||
|
||||
extern String GetFilePath(const String& path, const String& pathSplitter);
|
||||
|
||||
extern void GetRootFolderS(const String& path, String& folderName, String& resultPath);
|
||||
|
||||
extern void GetRootFolderS(const String& path, String& folderName);
|
||||
|
||||
extern String GetDirectoryName(const String& path);
|
||||
|
||||
#define AS_STRING(omg) String(omg)
|
||||
#define STR(omg) String(omg)
|
||||
|
||||
#endif
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
#ifndef PSDefault_h__
|
||||
#define PSDefault_h__
|
||||
|
||||
#include "PixelShader.h"
|
||||
#include <SoftGL/BRDF/lighting_core.h>
|
||||
|
||||
class PSDefault : public PixelShader
|
||||
{
|
||||
public:
|
||||
float3 camPosition;
|
||||
float4 diffuse;
|
||||
Texture* diffuse_map;
|
||||
float ior = 1.5f;
|
||||
float M = 0.7f;
|
||||
|
||||
PSDefault():diffuse_map(nullptr), diffuse(0){
|
||||
|
||||
}
|
||||
float4 Execute(float4* input) {
|
||||
using namespace lm;
|
||||
|
||||
//return float4(1, 1, 0, 1);
|
||||
//return float4(input[1].x, input[1].y, 0, 1);
|
||||
|
||||
float3 lightColor = float3(1.0f, 1.0f, 0.9f);
|
||||
|
||||
float3 ambientColor = float3(0.1f, 0.1f, 0.2f);
|
||||
|
||||
float3 N = lm::normalize(input[2].xyz());
|
||||
float3 L = lm::normalize(float3(1, 1, 1));
|
||||
float3 V = lm::normalize(camPosition - input[3].xyz());
|
||||
float3 H = normalize(L + V);
|
||||
|
||||
float NdotL = std::max<float>(0, lm::dot(N, L));
|
||||
float NdotV = std::max<float>(0, lm::dot(N, V));
|
||||
float LdotH = lm::dot(L, H);
|
||||
|
||||
float F = Fresnel(LdotH, ior);
|
||||
|
||||
float G = G_Cook_Torrance(N, H, V, L);
|
||||
|
||||
float D = D_Beckmann(H, N, M);
|
||||
|
||||
float r_microfacet = (F * G * D) / (4 * NdotL * NdotV + 1.0e-7) * MATH_PI* NdotL;
|
||||
|
||||
float4 diffuse = float4(0, 0, 0, 0);
|
||||
if (diffuse_map != nullptr) {
|
||||
diffuse = tex2D(diffuse_map, input[1].x(), input[1].y(), TextureFilter::Bilinear);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
float3 result = float3(0, 0, 0);
|
||||
result = diffuse.xyz() * (lightColor * diffuse.xyz()) * NdotL + lightColor * r_microfacet + ambientColor * diffuse.xyz();
|
||||
|
||||
result = lm::saturate(result);
|
||||
|
||||
float4 retval;
|
||||
retval.xyz() = result;
|
||||
retval.w() = diffuse.w();
|
||||
return retval;
|
||||
}
|
||||
};
|
||||
#endif // PSDefault_h__
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include "PixelShader.h"
|
||||
#include <SoftGL/BRDF/lighting_core.h>
|
||||
|
||||
class PSDefaultColor : public PixelShader
|
||||
{
|
||||
public:
|
||||
float4 diffuse;
|
||||
|
||||
PSDefaultColor(): diffuse(1.0f, 1.0f, 1.0f, 1.0f){
|
||||
|
||||
}
|
||||
float4 Execute(float4* input) {
|
||||
return diffuse;
|
||||
}
|
||||
};
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
#ifndef PSFont_h__
|
||||
#define PSFont_h__
|
||||
|
||||
#include "PixelShader.h"
|
||||
|
||||
class PSFont : public PixelShader
|
||||
{
|
||||
public:
|
||||
float appTime;
|
||||
float4 diffuse;
|
||||
Texture2D* diffuseTex;
|
||||
|
||||
PSFont()
|
||||
{
|
||||
|
||||
}
|
||||
float4 Execute(float4* input)
|
||||
{
|
||||
float4 out;
|
||||
|
||||
tex2D(diffuseTex, &out, input[1].X, input[1].Y);
|
||||
|
||||
out = float4(1,1,1,1) - out;
|
||||
out.W = out.X;
|
||||
return out;
|
||||
}
|
||||
};
|
||||
#endif // PSFont_h__
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
#ifndef PSTextured_h__
|
||||
#define PSTextured_h__
|
||||
|
||||
#include "PixelShader.h"
|
||||
|
||||
class PSTextured : public PixelShader
|
||||
{
|
||||
public:
|
||||
float appTime;
|
||||
float4 diffuse;
|
||||
Texture2D* diffuseTex;
|
||||
|
||||
PSTextured()
|
||||
{
|
||||
|
||||
}
|
||||
float4 Execute(float4* input)
|
||||
{
|
||||
/* float f = (sinf(appTime * 4.0f) * 0.5f + 0.5f);
|
||||
float4 color = diffuse * (sinf((input[0].Y / 2.0f)) * 0.5f + 0.5f)* (cosf((input[0].X / 2.0f)) * 0.5f * f + 0.5f);
|
||||
color.W = 0.6f;*/
|
||||
//return color;
|
||||
//return diffuse;
|
||||
float4 out;
|
||||
sample2D(diffuseTex, &out, input[1].X, input[1].Y);
|
||||
|
||||
//out = float4(1,1,1,1) - out;
|
||||
out.W = 0.5f;
|
||||
//return float4(1,1,1,1);
|
||||
return out;
|
||||
|
||||
|
||||
|
||||
//return float4(1,1,0,1);
|
||||
}
|
||||
};
|
||||
#endif // PSTextured_h__
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
#ifndef PixelShader_h__
|
||||
#define PixelShader_h__
|
||||
|
||||
#include "IShader.h"
|
||||
#include "Texture.h"
|
||||
#include <cstdint>
|
||||
#include <LMath/lmath.h>
|
||||
|
||||
using namespace lm;
|
||||
|
||||
enum class TextureFilter {
|
||||
Point,
|
||||
Bilinear,
|
||||
Trilinear,
|
||||
Anisotropic
|
||||
};
|
||||
|
||||
#define CLIP -1231345391
|
||||
class PixelShader : public IShader {
|
||||
public:
|
||||
virtual ~PixelShader() {
|
||||
|
||||
}
|
||||
virtual float4 Execute(float4* input) = 0;
|
||||
float4 tex2D(Texture* tex, float tx, float ty, TextureFilter filter) {
|
||||
if (tex == nullptr) {
|
||||
return float4(0, 0, 0, 0);
|
||||
}
|
||||
auto width = tex->Desc().Width;
|
||||
auto height = tex->Desc().Height;
|
||||
auto bpp = tex->Desc().BytesPerPixel;
|
||||
|
||||
auto tw = (float)(width - 1);
|
||||
auto th = (float)(height - 1);
|
||||
|
||||
auto mips = tex->LockRead();
|
||||
|
||||
if (tx > 1.0f) {
|
||||
tx = 1.0f;
|
||||
}
|
||||
if (tx < 0.0f) {
|
||||
tx = 0.0f;
|
||||
}
|
||||
if (ty > 1.0f) {
|
||||
ty = 1.0f;
|
||||
}
|
||||
if (ty < 0.0f) {
|
||||
ty = 0.0f;
|
||||
}
|
||||
if (filter == TextureFilter::Bilinear) {
|
||||
float x = (tx * tw);
|
||||
float y = (ty * th);
|
||||
int px = (int)x;
|
||||
int py = (int)y;
|
||||
|
||||
float fx = x - px;
|
||||
float fy = y - py;
|
||||
float fx1 = 1.0f - fx;
|
||||
float fy1 = 1.0f - fy;
|
||||
|
||||
int w1 = (int)(fx1 * fy1 * 256.0f);
|
||||
int w2 = (int)(fx * fy1 * 256.0f);
|
||||
int w3 = (int)(fx1 * fy * 256.0f);
|
||||
int w4 = (int)(fx * fy * 256.0f);
|
||||
|
||||
auto mem = reinterpret_cast<const uint8_t*>(mips);
|
||||
|
||||
auto p1 = mem + ((py + 0)*width + (px + 0))* bpp;
|
||||
auto p2 = mem + ((py + 0)*width + (px + 1))* bpp;
|
||||
auto p3 = mem + ((py + 1)*width + (px + 0))* bpp;
|
||||
auto p4 = mem + ((py + 1)*width + (px + 1))* bpp;
|
||||
|
||||
int outr = p1[0] * w1 + p2[0] * w2 + p3[0] * w3 + p4[0] * w4;
|
||||
int outg = p1[1] * w1 + p2[1] * w2 + p3[1] * w3 + p4[1] * w4;
|
||||
int outb = p1[2] * w1 + p2[2] * w2 + p3[2] * w3 + p4[2] * w4;
|
||||
|
||||
return float4(
|
||||
((float)(outr >> 8)) / 255.0f,
|
||||
((float)(outg >> 8)) / 255.0f,
|
||||
((float)(outb >> 8)) / 255.0f,
|
||||
1.0f);
|
||||
|
||||
} else {
|
||||
tx += 0.5f / tw;
|
||||
ty += 0.5f / th;
|
||||
int x = (int)(tx * tw);
|
||||
int y = (int)(ty * th);
|
||||
auto ptr = reinterpret_cast<const uint8_t*>(mips);
|
||||
ptr += (y*width + x)* bpp;
|
||||
return float4(
|
||||
((float)ptr[0]) / 255.0f,
|
||||
((float)ptr[1]) / 255.0f,
|
||||
((float)ptr[2]) / 255.0f,
|
||||
1.0f);
|
||||
}
|
||||
}
|
||||
};
|
||||
#endif // PixelShader_h__
|
||||
@@ -0,0 +1,202 @@
|
||||
#include "RenderWindowXORG.h"
|
||||
|
||||
#if defined(LINUX)
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
RenderWindowXORG::RenderWindowXORG(uint16 width, uint16 height)
|
||||
:img(0)
|
||||
{
|
||||
display_name = XOpenDisplay(NULL);
|
||||
screen = DefaultScreen(display_name);
|
||||
depth = DefaultDepth(display_name,screen);
|
||||
connection = ConnectionNumber(display_name);
|
||||
|
||||
visual = DefaultVisual(display_name, 0);
|
||||
|
||||
|
||||
if(depth == 1)
|
||||
printf("You live in prehistoric times\n");
|
||||
else
|
||||
printf("You've got a coloured monitor with depth of %d\n",depth);
|
||||
|
||||
rootwindow = RootWindow(display_name,screen);
|
||||
|
||||
window = XCreateSimpleWindow(display_name, rootwindow,
|
||||
0, 0, width, height, 1, 0, 0);
|
||||
|
||||
gc = XCreateGC(display_name, window, 0, NULL);
|
||||
|
||||
XMapWindow(display_name, window);
|
||||
XFlush(display_name);
|
||||
XSynchronize(display_name, 1);
|
||||
}
|
||||
|
||||
int RenderWindowXORG::GetTop()
|
||||
{
|
||||
XWindowAttributes xwa;
|
||||
XGetWindowAttributes(display_name, window, &xwa);
|
||||
return xwa.y;
|
||||
}
|
||||
|
||||
int RenderWindowXORG::GetLeft()
|
||||
{
|
||||
XWindowAttributes xwa;
|
||||
XFlush(display_name);
|
||||
XGetWindowAttributes(display_name, window, &xwa);
|
||||
return xwa.x;
|
||||
}
|
||||
|
||||
void RenderWindowXORG::SetPosition(int top, int left)
|
||||
{
|
||||
XMoveWindow(display_name, window, top, left);
|
||||
XSync(display_name, 1);
|
||||
XFlush(display_name);
|
||||
XSynchronize(display_name, 1);
|
||||
}
|
||||
|
||||
|
||||
void RenderWindowXORG::Update()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void RenderWindowXORG::SetCaption(const String& caption)
|
||||
{
|
||||
XStoreName(display_name, window, caption.c_str());
|
||||
XFlush(display_name);
|
||||
}
|
||||
|
||||
int RenderWindowXORG::GetWindowHandle()
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int RenderWindowXORG::GetWidth()
|
||||
{
|
||||
XWindowAttributes xwa;
|
||||
XGetWindowAttributes(display_name, window, &xwa);
|
||||
return xwa.width;
|
||||
}
|
||||
|
||||
int RenderWindowXORG::GetHeight()
|
||||
{
|
||||
XWindowAttributes xwa;
|
||||
XGetWindowAttributes(display_name, window, &xwa);
|
||||
return xwa.height;
|
||||
}
|
||||
|
||||
void RenderWindowXORG::SetSize(int w, int h)
|
||||
{
|
||||
XResizeWindow(display_name, window, w, h);
|
||||
XFlush(display_name);
|
||||
XSync(display_name, 1);
|
||||
}
|
||||
|
||||
const String& RenderWindowXORG::GetCaption()
|
||||
{
|
||||
return String("Not yet implemented");
|
||||
}
|
||||
|
||||
bool RenderWindowXORG::IsFullScreen()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void RenderWindowXORG::SetFullScreen(bool state)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool RenderWindowXORG::SwitchMode(bool fullscreen)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void RenderWindowXORG::SetFullscreenMode(DisplayMode mode)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void RenderWindowXORG::Present(Texture2D* tex)
|
||||
{
|
||||
|
||||
// char buf[256];
|
||||
|
||||
|
||||
|
||||
|
||||
if(img == 0)
|
||||
{
|
||||
// SetCaption("Create image!");
|
||||
img = XCreateImage(display_name, visual, 24, ZPixmap, 0, (char *)tex->getBuffer()->getDataPtr(), tex->width, tex->height, 32, 0);
|
||||
}
|
||||
|
||||
|
||||
XPutImage(display_name, window, gc, img, 0, 0, 0, 0, tex->width, tex->height);
|
||||
XFlushGC(display_name, gc);
|
||||
XFlush(display_name);
|
||||
XSync(display_name, true);
|
||||
|
||||
|
||||
|
||||
// sprintf(buf, "Data ptr = 0x%x", img->data);
|
||||
|
||||
// SetCaption(String(buf));
|
||||
|
||||
// img->data = NULL;
|
||||
// XDestroyImage(img);
|
||||
|
||||
|
||||
}
|
||||
|
||||
void RenderWindowXORG::OnActivate()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void RenderWindowXORG::OnDeactivate()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void RenderWindowXORG::OnResize()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool RenderWindowXORG::IsActive()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RenderWindowXORG::IsModeSwitching()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void RenderWindowXORG::SetCursorVisible(bool state)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool RenderWindowXORG::IsCursorVisible()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void RenderWindowXORG::CenterWindow()
|
||||
{
|
||||
int dw = DisplayWidth(display_name,screen);
|
||||
int dh = DisplayHeight(display_name,screen);
|
||||
|
||||
int ww = GetWidth();
|
||||
int wh = GetHeight();
|
||||
int px = (dw - ww) / 2;
|
||||
int py = (dh - wh) / 2;
|
||||
|
||||
SetPosition(px, py);
|
||||
XFlush(display_name);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,54 @@
|
||||
#ifndef RENDERWINDOWXORG_H
|
||||
#define RENDERWINDOWXORG_H
|
||||
|
||||
#if defined(LINUX)
|
||||
|
||||
#include "IRenderWindow.h"
|
||||
#include<X11/Xlib.h>
|
||||
#include<X11/Xutil.h>
|
||||
#include<stdio.h>
|
||||
|
||||
class RenderWindowXORG : public IRenderWindow
|
||||
{
|
||||
public:
|
||||
RenderWindowXORG(uint16 width, uint16 height);
|
||||
void Update();
|
||||
void SetCaption(const String& caption);
|
||||
int GetWindowHandle();
|
||||
int GetWidth();
|
||||
int GetHeight();
|
||||
void SetSize(int w, int h);
|
||||
const String& GetCaption();
|
||||
|
||||
int GetTop();
|
||||
int GetLeft();
|
||||
void SetPosition(int top, int left);
|
||||
|
||||
bool IsFullScreen();
|
||||
void SetFullScreen(bool state);
|
||||
bool SwitchMode(bool fullscreen);
|
||||
void SetFullscreenMode(DisplayMode mode);
|
||||
|
||||
void Present(Texture2D* tex);
|
||||
|
||||
void OnActivate();
|
||||
void OnDeactivate();
|
||||
void OnResize();
|
||||
bool IsActive();
|
||||
bool IsModeSwitching();
|
||||
void SetCursorVisible(bool state);
|
||||
bool IsCursorVisible();
|
||||
void CenterWindow();
|
||||
private:
|
||||
uint8_t* image32;
|
||||
Visual *visual;
|
||||
GC gc;
|
||||
Display *display_name;
|
||||
XImage* img;
|
||||
int depth,screen,connection;
|
||||
Window window, rootwindow;
|
||||
};
|
||||
|
||||
#endif //LINUX
|
||||
|
||||
#endif // RENDERWINDOWXORG_H
|
||||
@@ -0,0 +1,351 @@
|
||||
#include "RenderWindow.h"
|
||||
|
||||
|
||||
#include <Windows.h>
|
||||
#include <WinUser.h>
|
||||
|
||||
RenderWindow::RenderWindow()
|
||||
:UpdateCamera(false) {
|
||||
bFullscreen = false;
|
||||
bActive = true;
|
||||
bModeSwitching = false;
|
||||
bCursorVisible = true;
|
||||
bAltEnterLocked = false;
|
||||
|
||||
width = 256;
|
||||
height = 256;
|
||||
|
||||
g_hInst = GetModuleHandle(NULL);
|
||||
g_hwnd = NULL;
|
||||
|
||||
//memset(&g_wndClass,0,sizeof(WNDCLASSEX));
|
||||
|
||||
WNDCLASSEX g_wndClass = { NULL };
|
||||
|
||||
g_wndClass.cbSize = sizeof(WNDCLASSEX);
|
||||
g_wndClass.cbClsExtra = NULL;
|
||||
g_wndClass.cbWndExtra = NULL;
|
||||
g_wndClass.hbrBackground = (HBRUSH)GetStockObject(1);
|
||||
g_wndClass.hCursor = (HCURSOR)LoadCursor(NULL, IDC_ARROW);
|
||||
g_wndClass.hIcon = LoadIcon(g_hInst, IDI_APPLICATION);
|
||||
g_wndClass.hIconSm = LoadIcon(g_hInst, IDI_APPLICATION);
|
||||
g_wndClass.hInstance = g_hInst;
|
||||
g_wndClass.lpfnWndProc = &RenderWindow::WndProc;
|
||||
g_wndClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
|
||||
g_wndClass.lpszMenuName = NULL;
|
||||
g_wndClass.lpszClassName = _text("Onotole");
|
||||
|
||||
if (!RegisterClassEx(&g_wndClass)) {
|
||||
MessageBox(g_hwnd, _text("Can not create window class! We all gonna die!!"), _text("OH SHIT!"), MB_OK);
|
||||
}
|
||||
|
||||
|
||||
//calculate window size
|
||||
RECT NewWindowSize;
|
||||
NewWindowSize.top = 30;
|
||||
NewWindowSize.left = 300;
|
||||
NewWindowSize.bottom = NewWindowSize.top + height;
|
||||
NewWindowSize.right = NewWindowSize.left + width;
|
||||
|
||||
AdjustWindowRect(&NewWindowSize, WS_OVERLAPPEDWINDOW, false);
|
||||
|
||||
/*WS_MINIMIZEBOX
|
||||
WS_MAXIMIZEBOX*/
|
||||
|
||||
|
||||
if (!(g_hwnd = CreateWindowEx(NULL, _text("Onotole"), _text("LifeEngine render window"), WS_OVERLAPPEDWINDOW,
|
||||
NewWindowSize.left, NewWindowSize.top, NewWindowSize.right - NewWindowSize.left, NewWindowSize.bottom - NewWindowSize.top, NULL, NULL, g_hInst, NULL))) {
|
||||
MessageBox(g_hwnd, _text("Can not create window!"), _text("Can not create window!"), MB_OK);
|
||||
return;
|
||||
}
|
||||
|
||||
ShowWindow(g_hwnd, SW_SHOWNORMAL);
|
||||
SetForegroundWindow(g_hwnd);
|
||||
SetFocus(g_hwnd);
|
||||
|
||||
|
||||
ZeroMemory(&mode, sizeof(DEVMODE));
|
||||
mode.dmSize = sizeof(DEVMODE);
|
||||
EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &mode);
|
||||
|
||||
RenderWindow* ptr = this;
|
||||
LONG_PTR val = (LONG_PTR)ptr;
|
||||
SetWindowLongPtr(g_hwnd, GWLP_USERDATA, val);
|
||||
|
||||
fsMode.width = 640;
|
||||
fsMode.height = 480;
|
||||
fsMode.refreshRate = 60;
|
||||
fsMode.bpp = 4;
|
||||
|
||||
::ZeroMemory(&bitmapInfo, sizeof(BITMAPINFOHEADER));
|
||||
bitmapInfo.biSize = sizeof(BITMAPINFOHEADER);
|
||||
bitmapInfo.biWidth = width;
|
||||
bitmapInfo.biHeight = -height;
|
||||
bitmapInfo.biPlanes = 1;
|
||||
bitmapInfo.biBitCount = 32;
|
||||
bitmapInfo.biCompression = 0;
|
||||
bitmapInfo.biSizeImage = width * height * 4;
|
||||
|
||||
info.bmiHeader = bitmapInfo;
|
||||
|
||||
context = ::GetDC(g_hwnd);
|
||||
|
||||
CenterWindow();
|
||||
}
|
||||
void RenderWindow::Update() {
|
||||
#ifdef L_WIN32
|
||||
MSG msg = { 0 };
|
||||
while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
|
||||
switch (msg.message) {
|
||||
case WM_QUIT:
|
||||
event_activate();
|
||||
exit(0);
|
||||
|
||||
break;
|
||||
}
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
void RenderWindow::SetCaption(const String& val) {
|
||||
caption = val;
|
||||
SetWindowText(g_hwnd, caption.c_str());
|
||||
}
|
||||
void RenderWindow::SetFullScreen(bool state) {
|
||||
bFullscreen = state;
|
||||
}
|
||||
bool RenderWindow::IsFullScreen() {
|
||||
return bFullscreen;
|
||||
}
|
||||
RenderWindow::~RenderWindow(void) {
|
||||
ChangeDisplaySettings(&mode, 0);
|
||||
}
|
||||
|
||||
|
||||
void RenderWindow::OnActivate() {
|
||||
bActive = true;
|
||||
event_activate();
|
||||
}
|
||||
void RenderWindow::OnDeactivate() {
|
||||
bActive = false;
|
||||
event_deactivate();
|
||||
}
|
||||
void RenderWindow::OnResize() {
|
||||
if (!IsFullScreen() || !bModeSwitching) {
|
||||
RECT r;
|
||||
::GetClientRect(g_hwnd, &r);
|
||||
width = r.right - r.left;
|
||||
height = r.bottom - r.top;
|
||||
|
||||
::ZeroMemory(&bitmapInfo, sizeof(BITMAPINFOHEADER));
|
||||
bitmapInfo.biSize = sizeof(BITMAPINFOHEADER);
|
||||
bitmapInfo.biWidth = width;
|
||||
bitmapInfo.biHeight = -height;
|
||||
bitmapInfo.biPlanes = 1;
|
||||
bitmapInfo.biBitCount = 32;
|
||||
bitmapInfo.biCompression = 0;
|
||||
bitmapInfo.biSizeImage = width * height * 4;
|
||||
|
||||
info.bmiHeader = bitmapInfo;
|
||||
}
|
||||
event_resize();
|
||||
}
|
||||
bool RenderWindow::IsActive() {
|
||||
return bActive;
|
||||
}
|
||||
bool RenderWindow::IsModeSwitching() {
|
||||
return bModeSwitching;
|
||||
}
|
||||
void RenderWindow::SetCursorVisible(bool state) {
|
||||
bCursorVisible = state;
|
||||
}
|
||||
bool RenderWindow::IsCursorVisible() {
|
||||
return bCursorVisible;
|
||||
}
|
||||
|
||||
|
||||
bool RenderWindow::SwitchMode(bool fullscreen) {
|
||||
bFullscreen = fullscreen;
|
||||
|
||||
if (bFullscreen) {
|
||||
bModeSwitching = true;
|
||||
DEVMODE fmode;
|
||||
ZeroMemory(&fmode, sizeof(DEVMODE));
|
||||
fmode.dmSize = sizeof(DEVMODE);
|
||||
fmode.dmPelsWidth = fsMode.width;
|
||||
fmode.dmPelsHeight = fsMode.height;
|
||||
fmode.dmBitsPerPel = mode.dmBitsPerPel;
|
||||
fmode.dmDisplayFrequency = fsMode.refreshRate;
|
||||
fmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY;
|
||||
|
||||
//if(ChangeDisplaySettings(&fmode,0)!= DISP_CHANGE_SUCCESSFUL)
|
||||
// return false;
|
||||
|
||||
SetWindowLong(g_hwnd, GWL_EXSTYLE, WS_EX_APPWINDOW | WS_EX_TOPMOST);
|
||||
SetWindowLong(g_hwnd, GWL_STYLE, WS_POPUP);
|
||||
SetWindowPos(g_hwnd, HWND_TOPMOST, 0, 0, fsMode.width, fsMode.height, SWP_SHOWWINDOW | SWP_FRAMECHANGED);
|
||||
bModeSwitching = false;
|
||||
} else {
|
||||
//if(ChangeDisplaySettings(&mode_window,0)!= DISP_CHANGE_SUCCESSFUL)
|
||||
// return false;
|
||||
SetWindowLong(g_hwnd, GWL_EXSTYLE, WS_EX_APPWINDOW);
|
||||
SetWindowLong(g_hwnd, GWL_STYLE, WS_OVERLAPPEDWINDOW);
|
||||
SetSize(width, height);
|
||||
CenterWindow();
|
||||
}
|
||||
event_switch_fullscreen();
|
||||
return true;
|
||||
}
|
||||
void RenderWindow::CenterWindow() {
|
||||
int mx = GetSystemMetrics(SM_CXSCREEN);
|
||||
int my = GetSystemMetrics(SM_CYSCREEN);
|
||||
|
||||
int nx = (mx - width) / 2;
|
||||
int ny = (my - height) / 2;
|
||||
|
||||
SetWindowPos(g_hwnd, NULL, nx, ny, -1, -1,
|
||||
SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
|
||||
}
|
||||
void RenderWindow::SetFullscreenMode(DisplayMode _mode) {
|
||||
fsMode = _mode;
|
||||
}
|
||||
void RenderWindow::SetSize(int w, int h) {
|
||||
if (!IsFullScreen()) {
|
||||
width = w;
|
||||
height = h;
|
||||
RECT NewWindowSize;
|
||||
NewWindowSize.top = 50;
|
||||
NewWindowSize.left = 50;
|
||||
NewWindowSize.bottom = NewWindowSize.top + h;
|
||||
NewWindowSize.right = NewWindowSize.left + w;
|
||||
|
||||
AdjustWindowRect(&NewWindowSize, WS_OVERLAPPEDWINDOW, false);
|
||||
SetWindowPos(g_hwnd, HWND_TOP, NewWindowSize.left, NewWindowSize.top, NewWindowSize.right - NewWindowSize.left, NewWindowSize.bottom - NewWindowSize.top, SWP_SHOWWINDOW | SWP_FRAMECHANGED);
|
||||
//::MoveWindow(g_hwnd,NewWindowSize.left, NewWindowSize.top, NewWindowSize.right - NewWindowSize.left, NewWindowSize.bottom - NewWindowSize.top, true);
|
||||
CenterWindow();
|
||||
}
|
||||
}
|
||||
LRESULT __stdcall RenderWindow::WndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) {
|
||||
switch (message) {
|
||||
case WM_SIZE:
|
||||
{
|
||||
|
||||
if (wparam != SIZE_MINIMIZED) {
|
||||
LONG_PTR val = GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
if (val) {
|
||||
RenderWindow* wnd = (RenderWindow*)val;
|
||||
wnd->OnResize();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WM_SETCURSOR:
|
||||
{
|
||||
static bool hiddencursor = false;
|
||||
WORD ht = LOWORD(lparam);
|
||||
|
||||
LONG_PTR val = GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
if (val) {
|
||||
RenderWindow* wnd = (RenderWindow*)val;
|
||||
if (wnd->IsCursorVisible()) {
|
||||
ShowCursor(true);
|
||||
} else {
|
||||
if (HTCLIENT == ht && !hiddencursor) {
|
||||
hiddencursor = true;
|
||||
ShowCursor(false);
|
||||
} else if (HTCLIENT != ht && hiddencursor) {
|
||||
hiddencursor = false;
|
||||
ShowCursor(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
break;
|
||||
case WM_ACTIVATE: //Catch Alt + Tab
|
||||
{
|
||||
switch (wparam) {
|
||||
case WA_ACTIVE:
|
||||
{
|
||||
LONG_PTR val = GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
if (val) {
|
||||
RenderWindow* wnd = (RenderWindow*)val;
|
||||
wnd->OnActivate();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WA_INACTIVE:
|
||||
{
|
||||
LONG_PTR val = GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
if (val) {
|
||||
RenderWindow* wnd = (RenderWindow*)val;
|
||||
wnd->OnDeactivate();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WM_DESTROY:
|
||||
PostQuitMessage(0);
|
||||
DestroyWindow(hwnd);
|
||||
break;
|
||||
case WM_SYSKEYDOWN:
|
||||
switch (wparam) {
|
||||
case VK_RETURN:
|
||||
{
|
||||
if (GetKeyState(VK_MENU)) //Alt + Enter
|
||||
{
|
||||
LONG_PTR val = GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
if (val) {
|
||||
|
||||
RenderWindow* wnd = (RenderWindow*)val;
|
||||
if (!wnd->IsAltEnterLocked()) {
|
||||
wnd->SetAltEnterLocked(true);
|
||||
wnd->SwitchMode(!wnd->IsFullScreen());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case WM_SYSKEYUP:
|
||||
{
|
||||
switch (wparam) {
|
||||
case VK_RETURN:
|
||||
{
|
||||
LONG_PTR val = GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
if (val) {
|
||||
|
||||
RenderWindow* wnd = (RenderWindow*)val;
|
||||
wnd->SetAltEnterLocked(false);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WM_KEYDOWN:
|
||||
switch (wparam) {
|
||||
case VK_SPACE:
|
||||
{
|
||||
LONG_PTR val = GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
if (val) {
|
||||
RenderWindow* wnd = (RenderWindow*)val;
|
||||
wnd->UpdateCamera = !wnd->UpdateCamera;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case VK_ESCAPE:
|
||||
PostQuitMessage(0);
|
||||
exit(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return DefWindowProc(hwnd, message, wparam, lparam);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
#pragma once
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <SoftGL/IRenderWindow.h>
|
||||
|
||||
class RenderWindow : public IRenderWindow {
|
||||
public:
|
||||
/*virtual ~RenderWindow(void) {}
|
||||
virtual void Update() = 0;
|
||||
virtual void SetCaption(const String& caption) = 0;
|
||||
virtual int GetWindowHandle() = 0;
|
||||
virtual int GetWidth() = 0;
|
||||
virtual int GetHeight() = 0;
|
||||
virtual const String& GetCaption() = 0;*/
|
||||
|
||||
bool UpdateCamera;
|
||||
|
||||
RenderWindow();
|
||||
~RenderWindow(void);
|
||||
void Update();
|
||||
void SetCaption(const String& caption);
|
||||
std::size_t GetWindowHandle() { return (std::size_t)g_hwnd; }
|
||||
void SetSize(int w, int h);
|
||||
bool IsFullScreen();
|
||||
void SetFullScreen(bool state);
|
||||
bool SwitchMode(bool fullscreen);
|
||||
void SetFullscreenMode(DisplayMode mode);
|
||||
|
||||
|
||||
bool IsActive();
|
||||
bool IsModeSwitching();
|
||||
void SetCursorVisible(bool state);
|
||||
bool IsCursorVisible();
|
||||
void CenterWindow();
|
||||
|
||||
int GetWidth() {
|
||||
return width;
|
||||
}
|
||||
virtual int GetHeight() {
|
||||
return height;
|
||||
}
|
||||
const String& GetCaption() {
|
||||
return caption;
|
||||
}
|
||||
void SetAltEnterLocked(bool state) {
|
||||
bAltEnterLocked = state;
|
||||
}
|
||||
bool IsAltEnterLocked() {
|
||||
return bAltEnterLocked;
|
||||
}
|
||||
virtual void event_activate() {
|
||||
|
||||
}
|
||||
virtual void event_deactivate() {
|
||||
|
||||
}
|
||||
virtual void event_resize() {
|
||||
|
||||
}
|
||||
virtual void event_switch_fullscreen() {
|
||||
|
||||
}
|
||||
virtual void Present(Texture* tex) override {
|
||||
if (tex->Desc().BytesPerPixel == 4) {
|
||||
|
||||
SetDIBitsToDevice(
|
||||
context,
|
||||
0,
|
||||
0,
|
||||
tex->Desc().Width,
|
||||
tex->Desc().Height,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
tex->Desc().Height,
|
||||
tex->LockWrite(),
|
||||
&info,
|
||||
0
|
||||
);
|
||||
}else{
|
||||
DebugError("Can't present not 4 bytes pixels");
|
||||
}
|
||||
}
|
||||
protected:
|
||||
bool bAltEnterLocked;
|
||||
HINSTANCE g_hInst;
|
||||
HWND g_hwnd;
|
||||
DEVMODE mode;
|
||||
private:
|
||||
void OnActivate();
|
||||
void OnDeactivate();
|
||||
void OnResize();
|
||||
static LRESULT __stdcall WndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);
|
||||
|
||||
virtual int GetTop() override {
|
||||
RECT rect;
|
||||
GetWindowRect(g_hwnd, &rect);
|
||||
return rect.top;
|
||||
}
|
||||
|
||||
virtual int GetLeft() override {
|
||||
RECT rect;
|
||||
GetWindowRect(g_hwnd, &rect);
|
||||
return rect.left;
|
||||
}
|
||||
|
||||
virtual void SetPosition(int top, int left) override {
|
||||
RECT rect;
|
||||
GetWindowRect(g_hwnd, &rect);
|
||||
SetWindowPos(g_hwnd, NULL, left, top, GetWidth(), GetHeight(), 0);
|
||||
}
|
||||
|
||||
BITMAPINFOHEADER bitmapInfo;
|
||||
BITMAPINFO info;
|
||||
HDC context;
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
#ifndef RasterizerSettings_h__
|
||||
#define RasterizerSettings_h__
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
typedef uint32_t indices_t;
|
||||
#define MAX_TEX_SLOTS 16
|
||||
|
||||
static constexpr size_t InputElementNameLength = 16;
|
||||
|
||||
#endif // RasterizerSettings_h__
|
||||
Vendored
+22
@@ -0,0 +1,22 @@
|
||||
#ifndef Ray_h__
|
||||
#define Ray_h__
|
||||
|
||||
#include "LMath.h"
|
||||
|
||||
class Ray
|
||||
{
|
||||
public:
|
||||
float3 Origin;
|
||||
float3 Direction;
|
||||
Ray()
|
||||
:Origin(0,0,0), Direction(0,0,0)
|
||||
{
|
||||
|
||||
}
|
||||
Ray(const float3& orig, const float3& dir)
|
||||
{
|
||||
Origin = orig;
|
||||
Direction = dir;
|
||||
}
|
||||
};
|
||||
#endif // Ray_h__
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
#ifndef RegisterBlock_h__
|
||||
#define RegisterBlock_h__
|
||||
|
||||
#include <LMath/lmath.h>
|
||||
#include <array>
|
||||
|
||||
using namespace lm;
|
||||
|
||||
#define REG_COUNT 5
|
||||
|
||||
struct RegisterBlock {
|
||||
std::array<float4, REG_COUNT> reg;
|
||||
|
||||
inline static void Sub(const RegisterBlock& b1, const RegisterBlock& b2, RegisterBlock& result) {
|
||||
for (int i = 0; i < REG_COUNT; i++) {
|
||||
result.reg[i] = b1.reg[i] - b2.reg[i];
|
||||
}
|
||||
}
|
||||
inline static void Add(const RegisterBlock& b1, const RegisterBlock& b2, RegisterBlock& result) {
|
||||
for (int i = 0; i < REG_COUNT; i++) {
|
||||
result.reg[i] = b1.reg[i] + b2.reg[i];
|
||||
}
|
||||
}
|
||||
inline static void Mul(const RegisterBlock& b1, float val, RegisterBlock& result) {
|
||||
for (int i = 0; i < REG_COUNT; i++) {
|
||||
result.reg[i] = b1.reg[i] * val;
|
||||
}
|
||||
}
|
||||
inline static void Div(const RegisterBlock& b1, float val, RegisterBlock& result) {
|
||||
for (int i = 0; i < REG_COUNT; i++) {
|
||||
result.reg[i] = b1.reg[i] / val;
|
||||
}
|
||||
}
|
||||
inline static void Mul(RegisterBlock& b1, float val) {
|
||||
for (int i = 0; i < REG_COUNT; i++) {
|
||||
b1.reg[i] *= val;
|
||||
}
|
||||
}
|
||||
inline static void Div(RegisterBlock& b1, float val) {
|
||||
for (int i = 0; i < REG_COUNT; i++) {
|
||||
b1.reg[i] /= val;
|
||||
}
|
||||
}
|
||||
inline static void Clone(const RegisterBlock& from, RegisterBlock& to) {
|
||||
for (int i = 0; i < REG_COUNT; i++) {
|
||||
to.reg[i] = from.reg[i];
|
||||
}
|
||||
}
|
||||
};
|
||||
#endif // RegisterBlock_h__
|
||||
@@ -0,0 +1,7 @@
|
||||
#ifndef ResourceManager_h__
|
||||
#define ResourceManager_h__
|
||||
|
||||
#include "Buffer.h"
|
||||
|
||||
|
||||
#endif // ResourceManager_h__
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
TEMPLATE = lib
|
||||
CONFIG += debug \
|
||||
staticlib \
|
||||
warn_off
|
||||
|
||||
|
||||
DESTDIR = ../../bin
|
||||
CONFIG -= release \
|
||||
warn_on
|
||||
|
||||
HEADERS += \
|
||||
VSScreenSpace.h \
|
||||
VSDefault.h \
|
||||
Viewport.h \
|
||||
VertexShader.h \
|
||||
VertexBuffer.h \
|
||||
Vertex.h \
|
||||
float4.h \
|
||||
float3.h \
|
||||
Vector2D.h \
|
||||
Types.h \
|
||||
Tools.h \
|
||||
Timer.h \
|
||||
Texture2D.h \
|
||||
Scene.h \
|
||||
ResourceManager.h \
|
||||
RenderWindowXORG.h \
|
||||
RenderWindow.h \
|
||||
Renderer3D.h \
|
||||
Renderer.h \
|
||||
Ray.h \
|
||||
Quaternion.h \
|
||||
PSTextured.h \
|
||||
PSFont.h \
|
||||
PSDefault.h \
|
||||
Primitive.h \
|
||||
Plane.h \
|
||||
PixelShader.h \
|
||||
Mesh.h \
|
||||
Matrix4x4.h \
|
||||
Matrix3x3.h \
|
||||
LString.h \
|
||||
LMath.h \
|
||||
IShader.h \
|
||||
IRenderWindow.h \
|
||||
InputSystem.h \
|
||||
InputLayout.h \
|
||||
Inline.h \
|
||||
IndexBuffer.h \
|
||||
FpsCounter.h \
|
||||
DisplayMode.h \
|
||||
Delegate_base.h \
|
||||
Delegate.h \
|
||||
Camera.h \
|
||||
Buffer.h \
|
||||
BlockRasterizer.h \
|
||||
Bitmap.h \
|
||||
TextureSampler.h
|
||||
|
||||
SOURCES += \
|
||||
RenderWindowXORG.cpp \
|
||||
RenderWindow.cpp \
|
||||
Mesh.cpp \
|
||||
BlockRasterizerTest.cpp \
|
||||
BlockRasterizer.cpp
|
||||
|
||||
CONFIG += link_pkgconfig
|
||||
PKGCONFIG += x11
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
#ifndef StaticBuffer_h__
|
||||
#define StaticBuffer_h__
|
||||
|
||||
#include "Buffer.h"
|
||||
|
||||
template<typename T, size_t _Size>
|
||||
struct static_buffer : public Buffer {
|
||||
std::array<T, _Size> data;
|
||||
static_buffer() {
|
||||
|
||||
//static_assert(init.size() == Size, "Incorrect number of parameters");
|
||||
}
|
||||
static_buffer(const std::array<T, _Size>& values):data(values){
|
||||
|
||||
//static_assert(init.size() == Size, "Incorrect number of parameters");
|
||||
}
|
||||
|
||||
virtual void* GetPointer() override {
|
||||
return &data[0];
|
||||
}
|
||||
|
||||
virtual size_t Size() override {
|
||||
return _Size * sizeof(T);
|
||||
}
|
||||
|
||||
virtual size_t ItemSize() override {
|
||||
return sizeof(T);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // StaticBuffer_h__
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
#pragma once
|
||||
|
||||
#include "mip_utils.h"
|
||||
#include "Texture.h"
|
||||
#include <vector>
|
||||
#include <array>
|
||||
|
||||
template<size_t _BytesPerPixel, size_t _Width, size_t _Height, size_t _MaxMip = -1, size_t CurrentMip = 0, bool _lastMip = ((_Width == 1) && (_Height == 1)) || (CurrentMip == _MaxMip)>
|
||||
struct MipChain : MipChain<_BytesPerPixel, MipUtils::SmallerMipSize(_Width), MipUtils::SmallerMipSize(_Height), _MaxMip, CurrentMip + 1> {
|
||||
static constexpr auto Width = _Width;
|
||||
static constexpr auto Height = _Height;
|
||||
static constexpr auto BytesPerPixel = _BytesPerPixel;
|
||||
static_assert(MipUtils::IsValidMipSize(_Width), "Invalid MIP width, must be power of 2");
|
||||
static_assert(MipUtils::IsValidMipSize(_Height), "Invalid MIP height, must be power of 2");
|
||||
std::array<uint8_t, _Width * _Height * _BytesPerPixel> data;
|
||||
};
|
||||
|
||||
template<size_t _BytesPerPixel, size_t _Width, size_t _Height, size_t _MaxMip, size_t CurrentMip>
|
||||
struct MipChain<_BytesPerPixel, _Width, _Height, _MaxMip, CurrentMip, true> {
|
||||
void* GetPointer() {
|
||||
return &data[0];
|
||||
}
|
||||
const void* GetPointer() const {
|
||||
return &data[0];
|
||||
}
|
||||
|
||||
static constexpr size_t MipsCount = CurrentMip + 1;
|
||||
static constexpr auto Width = _Width;
|
||||
static constexpr auto Height = _Height;
|
||||
static constexpr auto BytesPerPixel = _BytesPerPixel;
|
||||
std::array<uint8_t, _Width * _Height * _BytesPerPixel> data;
|
||||
};
|
||||
|
||||
|
||||
struct DynamicMipChain {
|
||||
DynamicMipChain(size_t width, size_t height, size_t bytesPerPixel, size_t maxMip){
|
||||
size_t pixelsCount = 0;
|
||||
_mipsCount = 0;
|
||||
while(_mipsCount <= maxMip && (width > 0) && (height > 0)){
|
||||
pixelsCount += width * height;
|
||||
width >>= 1;
|
||||
height >>= 1;
|
||||
_mipsCount++;
|
||||
}
|
||||
_data.resize(pixelsCount * bytesPerPixel);
|
||||
}
|
||||
void* GetPointer() {
|
||||
return &_data[0];
|
||||
}
|
||||
const void* GetPointer() const {
|
||||
return &_data[0];
|
||||
}
|
||||
size_t Size() const{
|
||||
return _data.size();
|
||||
}
|
||||
size_t MipsCount() const {
|
||||
return _mipsCount;
|
||||
}
|
||||
private:
|
||||
size_t _mipsCount;
|
||||
std::vector<uint8_t> _data;
|
||||
};
|
||||
|
||||
|
||||
template<typename _Pointer, bool _IsConst = std::is_const<typename std::remove_pointer<_Pointer>::type>::value>
|
||||
struct PointerUtils {
|
||||
using raw_pointer = decltype(&(*std::declval<_Pointer>()));
|
||||
static raw_pointer GetWritable(_Pointer ptr) { return (raw_pointer)ptr->GetPointer(); }
|
||||
};
|
||||
|
||||
template<typename _Pointer>
|
||||
struct PointerUtils<_Pointer, true> {
|
||||
using raw_pointer = decltype(&(*std::declval<_Pointer>()));
|
||||
static typename std::remove_cv<std::remove_pointer<raw_pointer>>::type* GetWritable(_Pointer ptr) { return nullptr; }
|
||||
};
|
||||
|
||||
|
||||
template<typename _DataPointer>
|
||||
class StaticTexture : public Texture {
|
||||
public:
|
||||
StaticTexture(_DataPointer data, const TextureDescription& description) : Texture(description), _data(data) {}
|
||||
virtual void* LockWrite() override { return PointerUtils<_DataPointer>::GetWritable(_data); }
|
||||
virtual const void* LockRead() override { return _data->GetPointer(); }
|
||||
private:
|
||||
_DataPointer _data;
|
||||
};
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
#ifndef Texture_h__
|
||||
#define Texture_h__
|
||||
|
||||
#include "dynamic_buffer.h"
|
||||
#include "LString.h"
|
||||
#include "Bitmap.h"
|
||||
#include <stdio.h>
|
||||
#include "mip_utils.h"
|
||||
|
||||
struct Color24{
|
||||
uint8_t b;
|
||||
uint8_t g;
|
||||
uint8_t r;
|
||||
|
||||
void fromColor16(uint16_t value){
|
||||
b = (value & 0x1f) << 3;
|
||||
g = (value & 0x7e0) >> 3;
|
||||
r = (value & 0xf800) >> 8;
|
||||
}
|
||||
|
||||
uint16_t toColor16(){
|
||||
uint16_t result = b >> 3;
|
||||
result |= ((uint16_t)g >> 2) << 5;
|
||||
result |= ((uint16_t)r >> 3) << 11;
|
||||
return result;
|
||||
}
|
||||
|
||||
static Color24 lerp(Color24 left, Color24 right, uint16_t val, uint16_t maxVal){
|
||||
Color24 result;
|
||||
result.r = (int32_t)left.r + ((int32_t)(right.r - left.r) * (int32_t)val) / (int32_t)maxVal;
|
||||
result.g = (int32_t)left.g + ((int32_t)(right.g - left.g) * (int32_t)val) / (int32_t)maxVal;
|
||||
result.b = (int32_t)left.b + ((int32_t)(right.b - left.b) * (int32_t)val) / (int32_t)maxVal;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct TextureDescription {
|
||||
size_t Width;
|
||||
size_t Height;
|
||||
size_t Depth;
|
||||
size_t BytesPerPixel;
|
||||
size_t MipCount;
|
||||
};
|
||||
|
||||
struct Texture {
|
||||
Texture(const TextureDescription& description) : _description(description) {
|
||||
_depthStride = 0;
|
||||
size_t width = _description.Width;
|
||||
size_t height = _description.Height;
|
||||
for (size_t i = 0; i < _description.MipCount; ++i) {
|
||||
_depthStride += _description.BytesPerPixel * width * height;
|
||||
width = MipUtils::SmallerMipSize(width);
|
||||
height = MipUtils::SmallerMipSize(height);
|
||||
}
|
||||
}
|
||||
virtual void* LockWrite() = 0;
|
||||
virtual const void* LockRead() = 0;
|
||||
virtual ~Texture() = default;
|
||||
const TextureDescription& Desc() const {
|
||||
return _description;
|
||||
}
|
||||
private:
|
||||
size_t _depthStride;
|
||||
TextureDescription _description;
|
||||
};
|
||||
|
||||
#endif // Texture_h__
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
#ifndef TEXTURESAMPLER_H
|
||||
#define TEXTURESAMPLER_H
|
||||
|
||||
#include "Texture.h"
|
||||
|
||||
static inline uint32_t sample2D(Texture* tex, float tX, float tY)
|
||||
{
|
||||
if(tex == nullptr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
tX = lm::clamp(tX, 0.0f, 1.0f);
|
||||
tY = lm::clamp(tY, 0.0f, 1.0f);
|
||||
|
||||
tY = 1.0f - tY;
|
||||
|
||||
|
||||
|
||||
int x = static_cast<int>((tX * ((float)tex->Desc().Width - 1.0f)));
|
||||
int y = static_cast<int>((tY * ((float)tex->Desc().Height - 1.0f)));
|
||||
auto ptr = reinterpret_cast<const uint8_t*>(tex->LockRead());
|
||||
|
||||
|
||||
float pX = tX * (float)tex->Desc().Width;
|
||||
float pY = tY * (float)tex->Desc().Height;
|
||||
|
||||
uint32_t frX = (uint32_t)((pX - (float)((int)pX))* 255.0f);
|
||||
uint32_t frY = (uint32_t)((pY - (float)((int)pY))* 255.0f);
|
||||
|
||||
auto ptr2 = reinterpret_cast<const uint32_t*>(tex->LockRead());
|
||||
|
||||
uint32_t color;
|
||||
// if(tex->bpp < 4)
|
||||
// {
|
||||
uint32_t tl = 0xff000000;
|
||||
/* uint32_t tr = 0xff000000;
|
||||
uint32_t rl = 0xff000000;
|
||||
uint32_t rr = 0xff000000;*/
|
||||
|
||||
memcpy(&tl, ptr+ (y*tex->Desc().Width + x)* tex->Desc().BytesPerPixel, tex->Desc().BytesPerPixel);
|
||||
//memcpy(&tr, ptr+ (y*tex->width + x + 1)* tex->bpp, 3);
|
||||
// memcpy(&rl, ptr+ ((y + 1)*tex->width + x)* tex->bpp, 3);
|
||||
//memcpy(&rr, ptr+ ((y + 1)*tex->width + x + 1)* tex->bpp, 3);
|
||||
|
||||
color = tl;// blendrgb ( blendrgb ( tl, tr, frX), blendrgb ( rl, rr, frX), frY);
|
||||
|
||||
/* }
|
||||
else
|
||||
{
|
||||
|
||||
int32 x1 = x;
|
||||
int32 x2 = x + 1;
|
||||
int32 x3 = x;
|
||||
int32 x4 = x + 1;
|
||||
|
||||
int32 y1 = y;
|
||||
int32 y2 = y;
|
||||
int32 y3 = (y + 1);
|
||||
int32 y4 = (y + 1);
|
||||
|
||||
x1 = clampInt(x1, 0, tex->width - 1);
|
||||
x2 = clampInt(x2, 0, tex->width - 1);
|
||||
x3 = clampInt(x3, 0, tex->width - 1);
|
||||
x4 = clampInt(x4, 0, tex->width - 1);
|
||||
|
||||
|
||||
y1 = clampInt(y1, 0, tex->height - 1);
|
||||
y2 = clampInt(y2, 0, tex->height - 1);
|
||||
y3 = clampInt(y3, 0, tex->height - 1);
|
||||
y4 = clampInt(y4, 0, tex->height - 1);
|
||||
|
||||
|
||||
|
||||
|
||||
uint32_t tl = ptr2[y1 * tex->width + x1];
|
||||
uint32_t tr = ptr2[y2 * tex->width + x2];
|
||||
uint32_t rl = ptr2[y3 * tex->width + x3];
|
||||
uint32_t rr = ptr2[y4 * tex->width + x4];
|
||||
|
||||
color = blendrgb ( blendrgb ( tl, tr, frX), blendrgb ( rl, rr, frX), frY);
|
||||
}*/
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
#endif // TEXTURESAMPLER_H
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
#ifndef Tools_h__
|
||||
#define Tools_h__
|
||||
|
||||
template<typename T>
|
||||
void PrintBits(const T& val)
|
||||
{
|
||||
int countBytes = sizeof(T);
|
||||
int countBits = countBytes * 8;
|
||||
char* ptr = (char*)&val;
|
||||
|
||||
for(int i = 0; i < countBytes; i++)
|
||||
{
|
||||
char b = *ptr;
|
||||
for(int j = 7; j >= 0; j--)
|
||||
{
|
||||
char val = (b & (1 << j)) >> j;
|
||||
printf("%i", val);
|
||||
}
|
||||
printf(" ");
|
||||
ptr++;
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
}
|
||||
#endif // Tools_h__
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
#ifndef VSDefault_h__
|
||||
#define VSDefault_h__
|
||||
|
||||
#include "VertexShader.h"
|
||||
|
||||
class VSDefault : public VertexShader
|
||||
{
|
||||
public:
|
||||
float4x4 mWorld;
|
||||
float4x4 mView;
|
||||
float4x4 mProj;
|
||||
|
||||
VSDefault(){
|
||||
//declare shader inputs
|
||||
inputs.push_back(String("POSITION"));
|
||||
inputs.push_back(String("TEXCOORD"));
|
||||
inputs.push_back(String("NORMAL"));
|
||||
}
|
||||
int Execute(float4** input, float4* output)
|
||||
{
|
||||
float4x4 wv = lm::mul(mView, mWorld);
|
||||
float4x4 wvp = lm::mul(mProj, wv);
|
||||
|
||||
float4 position = *input[0];
|
||||
position.w() = 1.0f;
|
||||
|
||||
float3x3 world;
|
||||
world[0] = mWorld[0].xyz();
|
||||
world[1] = mWorld[1].xyz();
|
||||
world[2] = mWorld[2].xyz();
|
||||
|
||||
|
||||
output[0] = lm::mul(wvp, position);
|
||||
output[1] = *input[1];
|
||||
output[2].xyz() = lm::mul(world, (*input[2]).xyz());
|
||||
output[3].xyz() = lm::mul(mWorld, position).xyz();
|
||||
return 4;
|
||||
}
|
||||
};
|
||||
#endif // VSDefault_h__
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
#ifndef VSScreenSpace_h__
|
||||
#define VSScreenSpace_h__
|
||||
|
||||
|
||||
#include "VertexShader.h"
|
||||
|
||||
class VSScreenSpace : public VertexShader
|
||||
{
|
||||
public:
|
||||
//Matrix4x4 mWorld;
|
||||
//Matrix4x4 mView;
|
||||
//Matrix4x4 mProj;
|
||||
float width;
|
||||
float height;
|
||||
|
||||
float pX;
|
||||
float pY;
|
||||
|
||||
float screenWidth;
|
||||
float screenHeight;
|
||||
|
||||
|
||||
VSScreenSpace()
|
||||
{
|
||||
//declare shader inputs
|
||||
inputs.push_back(STR("POSITION"));
|
||||
inputs.push_back(STR("COLOR"));
|
||||
}
|
||||
int Execute(float4** input, float4* output)
|
||||
{
|
||||
//Matrix4x4 wv = mWorld * mView;
|
||||
//Matrix4x4 wvp = wv * mProj;
|
||||
float xScale = width / screenWidth;
|
||||
float yScale = height / screenHeight;
|
||||
|
||||
float4 position = (*input)[0];
|
||||
position.W = 1.0f;
|
||||
|
||||
position.X *= width;
|
||||
position.Y *= height;
|
||||
|
||||
position.X += pX;
|
||||
position.Y += pY;
|
||||
|
||||
position.X = position.X / screenWidth * 2.0f - 1.0f;
|
||||
position.Y = position.Y / screenHeight * 2.0f - 1.0f;
|
||||
|
||||
//Output.Position.xy = Output.Position.xy/float2(bbWidth, -bbHeight)*2.0f + float2(-1.0f,1.0f);
|
||||
|
||||
|
||||
output[0] = position;
|
||||
//Vec4Transform(position, wvp);
|
||||
//output[0] = position;
|
||||
|
||||
output[1] = (*input)[1];
|
||||
|
||||
return 2;
|
||||
}
|
||||
};
|
||||
#endif // VSScreenSpace_h__
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <LMath/lmath.h>
|
||||
|
||||
struct Vertex {
|
||||
lm::float4 Position;
|
||||
lm::float3 Normal;
|
||||
lm::float2 UV0;
|
||||
|
||||
Vertex() {
|
||||
|
||||
}
|
||||
Vertex(const lm::float4& pos, const lm::float2& tc) {
|
||||
Position = pos;
|
||||
UV0 = tc;
|
||||
}
|
||||
};
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
#ifndef VertexShader_h__
|
||||
#define VertexShader_h__
|
||||
|
||||
#include "IShader.h"
|
||||
|
||||
|
||||
|
||||
class VertexShader : public IShader
|
||||
{
|
||||
public:
|
||||
virtual ~VertexShader()
|
||||
{
|
||||
|
||||
}
|
||||
virtual int Execute(float4** input, float4* output) = 0;
|
||||
|
||||
};
|
||||
#endif // VertexShader_h__
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
#ifndef Viewport_h__
|
||||
#define Viewport_h__
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
class Viewport {
|
||||
public:
|
||||
int32_t width;
|
||||
int32_t height;
|
||||
float minZ;
|
||||
float maxZ;
|
||||
|
||||
Viewport(int32_t _width, int32_t _height, float _minZ, float _maxZ) {
|
||||
width = _width;
|
||||
height = _height;
|
||||
minZ = _minZ;
|
||||
maxZ = _maxZ;
|
||||
}
|
||||
~Viewport() {
|
||||
|
||||
}
|
||||
};
|
||||
#endif // Viewport_h__
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
#ifndef config_h__
|
||||
#define config_h__
|
||||
|
||||
#if (_MSC_VER)
|
||||
#include <memory>
|
||||
#endif
|
||||
|
||||
#if (_MSC_VER)
|
||||
template<typename T>
|
||||
using Pointer = std::shared_ptr<T>;
|
||||
#else
|
||||
template<typename T>
|
||||
using Pointer = T*;
|
||||
#endif
|
||||
|
||||
|
||||
#endif // config_h__
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
#ifndef dynamic_buffer_h__
|
||||
#define dynamic_buffer_h__
|
||||
|
||||
#include "Buffer.h"
|
||||
|
||||
template<typename T>
|
||||
struct dynamic_buffer : public Buffer{
|
||||
public:
|
||||
dynamic_buffer() : _size(0), _data(nullptr) {
|
||||
|
||||
}
|
||||
dynamic_buffer(size_t count) : _size(count * sizeof(T)){
|
||||
_data = new T[count];
|
||||
}
|
||||
dynamic_buffer(const dynamic_buffer& v) {
|
||||
_size = v._size;
|
||||
_data = new T[_size / sizeof(T)];
|
||||
memcpy(&_data[0], &v._data[0], _size);
|
||||
}
|
||||
dynamic_buffer(dynamic_buffer&& v) {
|
||||
_size = v._size;
|
||||
_data = v._data;
|
||||
|
||||
v._size = 0;
|
||||
v._data = nullptr;
|
||||
}
|
||||
|
||||
dynamic_buffer& operator=(const dynamic_buffer& v) {
|
||||
_size = v._size;
|
||||
_data = new T[_size / sizeof(T)];
|
||||
memcpy(&_data[0], &v._data[0], _size);
|
||||
return *this;
|
||||
}
|
||||
|
||||
dynamic_buffer& operator=(dynamic_buffer&& v) {
|
||||
_size = v._size;
|
||||
_data = v._data;
|
||||
|
||||
v._size = 0;
|
||||
v._data = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
~dynamic_buffer(){
|
||||
if (_data != nullptr) {
|
||||
delete[] _data;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void* GetPointer() override {
|
||||
return _data;
|
||||
}
|
||||
|
||||
virtual size_t Size() override {
|
||||
return _size;
|
||||
}
|
||||
|
||||
virtual size_t ItemSize() override {
|
||||
return sizeof(T);
|
||||
}
|
||||
|
||||
private:
|
||||
size_t _size;
|
||||
T* _data;
|
||||
};
|
||||
#endif // dynamic_buffer_h__
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
#ifndef mip_utils_h__
|
||||
#define mip_utils_h__
|
||||
|
||||
struct MipUtils {
|
||||
static constexpr size_t SmallerMipSize(size_t size) {
|
||||
return size > 1 ? size / 2 : size;
|
||||
}
|
||||
|
||||
static constexpr bool IsValidMipSize(size_t size) {
|
||||
return size == 0 ? false : (size == 1 ? true : (size % 2 == 0));
|
||||
}
|
||||
};
|
||||
|
||||
#endif // mip_utils_h__
|
||||
+207
@@ -0,0 +1,207 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Bitmap.h" />
|
||||
<ClInclude Include="BlockRasterizer.h" />
|
||||
<ClInclude Include="Buffer.h" />
|
||||
<ClInclude Include="config.h" />
|
||||
<ClInclude Include="Debug.h" />
|
||||
<ClInclude Include="DisplayMode.h" />
|
||||
<ClInclude Include="dynamic_buffer.h" />
|
||||
<ClInclude Include="FpsCounter.h" />
|
||||
<ClInclude Include="Graphics2D.h" />
|
||||
<ClInclude Include="IndexBuffer.h" />
|
||||
<ClInclude Include="InputLayout.h" />
|
||||
<ClInclude Include="InputSystem.h" />
|
||||
<ClInclude Include="IRenderWindow.h" />
|
||||
<ClInclude Include="IShader.h" />
|
||||
<ClInclude Include="LString.h" />
|
||||
<ClInclude Include="mip_utils.h" />
|
||||
<ClInclude Include="StaticTexture.h" />
|
||||
<ClInclude Include="static_mip_chain.h" />
|
||||
<ClInclude Include="PixelShader.h" />
|
||||
<ClInclude Include="PSDefault.h" />
|
||||
<ClInclude Include="PSFont.h" />
|
||||
<ClInclude Include="PSTextured.h" />
|
||||
<ClInclude Include="RasterizerSettings.h" />
|
||||
<ClInclude Include="Ray.h" />
|
||||
<ClInclude Include="RegisterBlock.h" />
|
||||
<ClInclude Include="RenderWindow.h" />
|
||||
<ClInclude Include="RenderWindowXORG.h" />
|
||||
<ClInclude Include="ResourceManager.h" />
|
||||
<ClInclude Include="StaticBuffer.h" />
|
||||
<ClInclude Include="static_vector.h" />
|
||||
<ClInclude Include="Texture.h" />
|
||||
<ClInclude Include="TextureSampler.h" />
|
||||
<ClInclude Include="texture_utils.h" />
|
||||
<ClInclude Include="Tools.h" />
|
||||
<ClInclude Include="Vertex.h" />
|
||||
<ClInclude Include="VertexShader.h" />
|
||||
<ClInclude Include="Viewport.h" />
|
||||
<ClInclude Include="VSDefault.h" />
|
||||
<ClInclude Include="VSScreenSpace.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="BlockRasterizer.cpp" />
|
||||
<ClCompile Include="RenderWindow.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="SoftGL.pro" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{C26A3393-5100-439B-8570-45FA48819037}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>softgl</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;_CRTDBG_MAP_ALLOC</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>D:\lmath\lmath;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;_CRTDBG_MAP_ALLOC</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>D:\lmath\lmath;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>Full</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>D:\lmath\lmath;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>D:\lmath\lmath;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,28 @@
|
||||
#ifndef mip_static_buffer_h__
|
||||
#define mip_static_buffer_h__
|
||||
|
||||
#include <array>
|
||||
|
||||
struct MipUtils {
|
||||
static constexpr size_t SmallerMipSize(size_t size){
|
||||
return size > 1 ? size / 2 : size;
|
||||
}
|
||||
};
|
||||
|
||||
template<size_t _BytesPerPixel, size_t _Width, size_t _Height, size_t _MaxMip = -1, size_t CurrentMip = 0>
|
||||
struct StaticMipChain {
|
||||
public:
|
||||
static constexpr uint32_t ChildWidth = MipUtils::SmallerMipSize(Width);
|
||||
static constexpr uint32_t ChildHeight = MipUtils::SmallerMipSize(Height);
|
||||
std::array<uint8_t, _Width * _Height * _BytesPerPixel> data;
|
||||
|
||||
StaticMipChain<_BytesPerPixel, ChildWidth, ChildHeight, _MaxMip, CurrentMip + 1> child;
|
||||
};
|
||||
|
||||
template<size_t _BytesPerPixel, size_t _MaxMip = -1, size_t CurrentMip = 0>
|
||||
struct StaticMipChain<_BytesPerPixel, 1, 1, _MaxMip, CurrentMip> {
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // mip_static_buffer_h__
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
#ifndef static_vector_h__
|
||||
#define static_vector_h__
|
||||
|
||||
#include <cstdint>
|
||||
#include "Debug.h"
|
||||
|
||||
template<typename T, size_t Capacity>
|
||||
class Static_vector {
|
||||
public:
|
||||
Static_vector():_size(0){
|
||||
|
||||
}
|
||||
static constexpr size_t capacity(){
|
||||
return Capacity;
|
||||
}
|
||||
bool full() const {
|
||||
return _size == Capacity;
|
||||
}
|
||||
bool empty() const {
|
||||
return _size == 0;
|
||||
}
|
||||
void clear(){
|
||||
_size = 0;
|
||||
}
|
||||
bool push_back(const T& value){
|
||||
if(full()){
|
||||
assert(false && "Can't push");
|
||||
return false;
|
||||
}
|
||||
_buffer[_size++] = value;
|
||||
return true;
|
||||
}
|
||||
void pop_back(){
|
||||
if(empty()){
|
||||
return;
|
||||
}
|
||||
--_size;
|
||||
}
|
||||
void remove(size_t id){
|
||||
if(id >= _size){
|
||||
return;
|
||||
}
|
||||
|
||||
_buffer[id] = _buffer[_size-1];
|
||||
--_size;
|
||||
}
|
||||
T& operator[](size_t id){
|
||||
SGL_ASSERT(id < _size, "Invalid index");
|
||||
return _buffer[id];
|
||||
}
|
||||
const T& operator[](size_t id) const{
|
||||
SGL_ASSERT(id < _size, "Invalid index");
|
||||
return _buffer[id];
|
||||
}
|
||||
size_t size() const {
|
||||
return _size;
|
||||
}
|
||||
private:
|
||||
T _buffer[Capacity];
|
||||
size_t _size;
|
||||
};
|
||||
#endif // static_vector_h__
|
||||
+176
@@ -0,0 +1,176 @@
|
||||
#ifndef texture_utils_h__
|
||||
#define texture_utils_h__
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "StaticTexture.h"
|
||||
#include "Bitmap.h"
|
||||
//#include <intrin.h>
|
||||
#include <LMath/lmath.h>
|
||||
|
||||
struct texture_utils {
|
||||
|
||||
template<typename SrcAccessor, typename DstAccessor>
|
||||
static bool copy(Texture* src, Texture* dst) {
|
||||
auto srcDesc = src->Desc();
|
||||
auto dstDesc = dst->Desc();
|
||||
|
||||
if (srcDesc.Width != dstDesc.Width || (srcDesc.Height != dstDesc.Height)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
auto* srcPtr = reinterpret_cast<const typename SrcAccessor::PixelDataType*>(src->LockRead());
|
||||
auto* dstPtr = reinterpret_cast<typename DstAccessor::PixelDataType*>(dst->LockWrite());
|
||||
|
||||
for (size_t y = 0; y < srcDesc.Height; ++y) {
|
||||
for (size_t x = 0; x < srcDesc.Width; ++x) {
|
||||
lm::float4 srcDataf = SrcAccessor::ConvertColor(srcPtr[x]);
|
||||
auto dstColor = DstAccessor::ConvertColor(srcDataf);
|
||||
dstPtr[x] = dstColor;
|
||||
}
|
||||
srcPtr += srcDesc.Width;
|
||||
dstPtr += srcDesc.Width;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
static bool fill(Texture* tex, T pixel_value) {
|
||||
if (tex == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (tex->Desc().BytesPerPixel != sizeof(T)) {
|
||||
//throw std::exception("Invalid pixel value specified");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto data = (T*)tex->LockWrite();
|
||||
|
||||
auto memsize = tex->Desc().Width * tex->Desc().Height * sizeof(pixel_value);
|
||||
|
||||
if((8 % (sizeof(T))) == 0 && (memsize % 8) == 0)
|
||||
{
|
||||
alignas(8) uint64_t block_value;
|
||||
T* blockPtr = (T*)&block_value;
|
||||
for (size_t i = 0; i < (8 / sizeof(T)); ++i) {
|
||||
blockPtr[i] = pixel_value;
|
||||
}
|
||||
|
||||
auto blockMem = (uint64_t*)data;
|
||||
for(size_t i = 0; i < (memsize / sizeof(block_value)); ++i)
|
||||
{
|
||||
blockMem[i] = block_value;
|
||||
}
|
||||
}
|
||||
|
||||
/*__m256i avxBlock;
|
||||
|
||||
if ((sizeof(avxBlock) % (sizeof(T))) == 0 && (memsize % sizeof(avxBlock)) == 0) {
|
||||
T* blockPtr = (T*)&avxBlock;
|
||||
for (size_t i = 0; i < (sizeof(avxBlock) / sizeof(T)); ++i) {
|
||||
blockPtr[i] = pixel_value;
|
||||
}
|
||||
|
||||
auto blockMem = (decltype(avxBlock)*)data;
|
||||
if(((size_t)blockMem % sizeof(avxBlock)) != 0)
|
||||
{
|
||||
throw std::exception("Memory is not SSE aligned");
|
||||
}
|
||||
const auto cnt = (memsize / sizeof(avxBlock));
|
||||
const auto last = blockMem + cnt;
|
||||
while(blockMem != last){
|
||||
|
||||
_mm256_store_si256(blockMem++, avxBlock);
|
||||
//_mm_store_si128(blockMem++, avxBlock);
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
//generic assign
|
||||
/*for (size_t i = 0; i < tex->Desc().Width * tex->Desc().Height; ++i) {
|
||||
data[i] = pixel_value;
|
||||
}*/
|
||||
return true;
|
||||
}
|
||||
|
||||
static Texture* LoadTexture(const std::string& path) {
|
||||
FILE *filePtr; //our file pointer
|
||||
BITMAPFILEHEADER bitmapFileHeader; //our bitmap file header
|
||||
BITMAPINFOHEADER bitmapInfoHeader;
|
||||
|
||||
//open filename in read binary mode
|
||||
filePtr = fopen(path.c_str(), "rb");
|
||||
if (filePtr == NULL)
|
||||
return nullptr;
|
||||
|
||||
//read the bitmap file header
|
||||
int read_cnt = fread(&bitmapFileHeader, 1, sizeof(BITMAPFILEHEADER), filePtr);
|
||||
|
||||
if (read_cnt != sizeof(BITMAPFILEHEADER)) {
|
||||
printf("EPIC FAIL!\n");
|
||||
}
|
||||
|
||||
|
||||
//verify that this is a bmp file by check bitmap id
|
||||
if (bitmapFileHeader.bfType != 0x4D42) {
|
||||
fclose(filePtr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//read the bitmap info header
|
||||
fread(&bitmapInfoHeader, 1, sizeof(BITMAPINFOHEADER), filePtr);
|
||||
|
||||
//move file point to the begging of bitmap data
|
||||
fseek(filePtr, bitmapFileHeader.bfOffBits, SEEK_SET);
|
||||
|
||||
auto width = bitmapInfoHeader.biWidth;
|
||||
auto height = bitmapInfoHeader.biHeight;
|
||||
auto bpp = bitmapInfoHeader.biBitCount / 8;
|
||||
|
||||
auto mips = std::make_shared<DynamicMipChain>(width, height, bpp, -1);
|
||||
|
||||
auto bytes_count = width * height * bpp;
|
||||
|
||||
auto stride = width * bpp;
|
||||
|
||||
auto padding = stride % 4 == 0 ? 0 : (4 - (stride % 4));
|
||||
|
||||
uint8_t* ptr = (uint8_t*)mips->GetPointer();
|
||||
|
||||
//read in the bitmap image data
|
||||
for (size_t y = 0; y < height; ++y) {
|
||||
auto dst_ptr = ptr + stride * (height - 1 - y);
|
||||
auto result = fread(dst_ptr, 1, stride, filePtr);
|
||||
if (padding != 0) {
|
||||
fseek(filePtr, padding, SEEK_CUR);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(filePtr);
|
||||
|
||||
|
||||
TextureDescription desc;
|
||||
desc.Width = width;
|
||||
desc.Height = height;
|
||||
desc.BytesPerPixel = bpp;
|
||||
desc.MipCount = mips->MipsCount();
|
||||
desc.Depth = 1;
|
||||
|
||||
return new StaticTexture<decltype(mips)>(mips, desc);
|
||||
}
|
||||
|
||||
/*auto bb = rasterizer.GetBackBuffer();
|
||||
uint32_t* pixels = (uint32_t*)bb->getBuffer()->getDataPtr();
|
||||
for (size_t y = 0; y < bb->height; ++y) {
|
||||
for (size_t x = 0; x < bb->width; ++x) {
|
||||
uint32_t xVal = (x * 0xff) / bb->width;
|
||||
uint32_t yVal = (y * 0xff) / bb->height;
|
||||
pixels[y * bb->width + x] = ((xVal & 0xff) << 16) | ((yVal & 0xff) << 8);
|
||||
}
|
||||
}*/
|
||||
};
|
||||
#endif // texture_utils_h__
|
||||
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
TEMPLATE = subdirs
|
||||
|
||||
SUBDIRS += \
|
||||
Demo_TexturedTriangle \
|
||||
SoftGL
|
||||
Reference in New Issue
Block a user