This commit is contained in:
2025-05-13 02:03:18 +03:00
parent 72860c7968
commit 90ef6120fd
463 changed files with 380758 additions and 2 deletions
+88
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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__
+69
View File
@@ -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;
};
+66
View File
@@ -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
View File
@@ -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;
};
+91
View File
@@ -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
View File
@@ -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__
+14
View File
@@ -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
View File
@@ -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
View File
@@ -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__
+70
View File
@@ -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;
}
};
+84
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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);
}
};
+6
View File
@@ -0,0 +1,6 @@
#ifndef IndexBuffer_h__
#define IndexBuffer_h__
#endif // IndexBuffer_h__
+59
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
+11
View File
@@ -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__
+22
View File
@@ -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
View File
@@ -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__
+7
View File
@@ -0,0 +1,7 @@
#ifndef ResourceManager_h__
#define ResourceManager_h__
#include "Buffer.h"
#endif // ResourceManager_h__
+68
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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>
+28
View File
@@ -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
View File
@@ -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
View File
@@ -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__