Code Monkey home page Code Monkey logo

renderxf's Introduction

renderXF

renderXF is a realtime, high performance, software renderer written in c#. Thanks to parallelization, direct memory pointers, bitwise operations, P/Invoke, stack allocation, and many more tricks, renderXF can handle lots of triangles. (350k @ ~6ms vertex processing). It's newer, faster and more powerful C++ variant can be found here (XFDraw).

renderXF has been also designed to be as simple and user friendly as possible. Because of this most of the code is composed of super simple commands, and buffer, shader and framebuffer initialization is also very simple. There is also a Wiki available to help with a quick start.

This software renderer is primarily focused on CAD thanks to its buffer caching capability. The current demo uses STL files. Unfortunately it is currently pixel fill rate limited.

Features

  • Fully programmable fragment shader
  • Partially programmable vertex shader
  • Built in camera transforms
  • Hardcoded performance features
  • Screenspace shaders
  • Direct blit (No bitmaps required)
  • GDI+ Interoperability (blit bitmaps onto the drawbuffer)
  • Draw and Depth Buffer caching
  • Simple Shader Code
  • Correct perspective interpolation
  • Very simple code (Easily portable into C++)
  • Drawing and depth buffer pointers available

Shader Code Example

First a shader has be declared with its type, and attribute settings.

Shader myShader = new Shader(VertexShader, FragmentShader, GLRenderMode.Line, GLExtraAttributeData.None);

For performance reasons, renderXF has its own built in camera position and rotation transformation system. It can be disabled via the SetOverrideCameraTransform() method. However the XYZ to XY transform systems are not programmable.

unsafe void VertexShader(float* OUT, float* IN, int FaceIndex)
{
    OUT[0] = IN[0] * 50f + lightPosition.x;
    OUT[1] = IN[1] * 50f + lightPosition.y;
    OUT[2] = IN[2] * 50f + lightPosition.z;
}
renderXF doesn't actually require a vertex shader unless manual camera is selected. This is in contrast with gouraud mode which requires only a vertex shader.

The fragment shader gives the user a byte pointer to the RGB pixel it will be setting. and an attribute pointer that will first give the interpolated vertex data, and then the extra attributes.

unsafe void FragmentShader(byte* BGR, float* Attributes, int FaceIndex)
{
    BGR[0] = (byte)(127.5f + 127.5f * Attributes[0]); //Blue Color
    BGR[1] = (byte)(127.5f + 127.5f * Attributes[1]); //Green Color
    BGR[2] = (byte)(127.5f + 127.5f * Attributes[2]); //Red Color
}

Screenshots

One Sample Per Triangle Shader: 97773 Triangles, 1920x1017, ~6.9ms

Flat Shading Example

Phong Shader: 558 Triangles, 1920x1017, 16ms

Phong Example

Phong Shader: 7980 Triangles, 1920x1017, 23ms

Phong Example

Hardcoded Gouraud Shader: 12938 Triangles, 1920x1017, ~6.1ms (as of v0.3.3)

Hardcoded Gouraud Shading Example

Hardcoded Gouraud Shader: 7980 Triangles, 1920x1017, ~6.3ms (as of v0.3.3)

Hardcoded Gouraud Shading Example

Wireframe Shader: 2208 Triangles, 1920x1017, ~0.47ms

Wireframe Mode

Both perpsective and orthographic modes are supported

Perspective and Orthographic interpolation

Late Wireframe supported with depth offset

Late Wireframe Example

Backface and Frontface culling

Culling Example

Screen space shaders

Post-Processing Example of screen space shader code:

unsafe void VignettePass(byte* BGR, int posX, int posY)
{
    float X = (2f * posX / renderWidth) - 1f;
    float Y = (2f * posY / renderHeight) - 1f;

    X = 1f - 0.5f * X * X;
    Y = X * (1f - 0.5f * Y * Y);

    BGR[0] = (byte)(BGR[0] * Y);
    BGR[1] = (byte)(BGR[1] * Y);
    BGR[2] = (byte)(BGR[2] * Y);
}

In use:

Shader VignetteShader = new Shader(VignettePass);

//Then during each frame, select and execute the shader
GL.SelectShader(VignetteShader);
GL.Pass();

Most Applicable Usage

The best case scenario to use this is for CAD applications, where frames are not continuously rendered. The software renderer is fast, but continuously rendering will crank your CPU temps high. The faster C++ version should probably be used for faster performance/less CPU fan noise. CAD Example

Buffer caching

The drawing and depth buffer can both be saved. This can hugely improve performance by just rendering what is moving.

//Initialize renderX and the Cached Buffer
renderX GL = new renderX(1920, 1080, this.Handle);
GLCachedBuffer cachedBuffer = new GLCachedBuffer(GL);

//Tell renderX to create a copy of the drawing and depth buffer upon draw
GL.CreateCopyOnDraw(cachedBuffer);
//Draw the object
GL.Draw();

//During the next frame, just recopy the old buffers:

//Copy with depth test:
GL.CopyFromCache(cachedBuffer, CopyMethod.SplitLoopDepthTest)
//Copy without depth test:
GL.CopyFromCache(cachedBuffer, CopyMethod.SplitLoop)

Caching Example

renderxf's People

Contributors

kf6kjg avatar theproadam avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

renderxf's Issues

Parallel rendering of multiple images (crash)

I am attempting to render multiple images at the same time. Occasionally I get AccessViolationException errors.
image

Each thread gets its own instance of renderX.

However if I render my images sequentially, which takes quite a bit of time, this is not the case. Is it a requirement of this library that there can only be a single instance running at a time?

"clear" color leak on edges when using BlitIntoBitmap

This might be a problem in my code, but my testing seems to be ruling that out.

Here's my camera setup:

GL.SetMatrixData(FOV, 128f, 1f); // 0=Perspective, 1=Orthographic

GL.ForceCameraPosition(new renderX2.Vector3(128f, 128f, 4000f));
GL.ForceCameraRotation(new renderX2.Vector3(0f, 180f, 0f)); // Angles degree

I then make a mesh that occupies from 0,0 to 256,256 - the Z value is variable. I've validated that the terrainVertexPoints array that feeds the vertex buffer has that range via debugging.

I then render the mesh using

GL.Clear(255, 0, 0);
GL.ClearDepth();
...
using (var vertexBuffer = new GLBuffer(terrainVertexPoints, terrainVertexStride, MemoryLocation.Heap))
{
	GL.SelectBuffer(vertexBuffer);
	var terrainShader = new Shader(shaders.ScaleCorrectionVS, shaders.TerrainShaderFS, GLRenderMode.Triangle);
	terrainShader.SetOverrideAttributeCount(terrainVertexStride - 3); // UVZ
	GL.SelectShader(terrainShader);
	GL.Draw();
}
...
GL.BlitIntoBitmap(mapbmp.Bitmap, new Point(0, 0), new Rectangle(0, 0, mapbmp.Width, mapbmp.Height)); // 1px clear color on top, left, and bottom.

You can see the 1 pixel red lines on the edges:
map-1-2001-1999-objects

To test what was going on:

  1. I changed to GL.SetMatrixData(FOV, 64f, 1f) so that I was certain that the terrain fully filled the viewport, and still got the same red lines.
  2. I changed the clear color, the lines changed to the same color.
  3. I tried adjusting the BlitIntoBitmap Point and Rectangle - this demonstrated the ability to remove the red "clear" color lines in some configurations, but at the cost of introducing black lines. This seems to indicate that there might be an off-by-one error or two in the BlitIntoBitmap method, but is not full proof.

NuGet publish?

Any chance of getting this officially published on NuGet? It'd make it far easier to utilize! :D

Blitting into a bitmap is a no-op

If you don't get to it first, I probably will.

Method renderX::BlitInto(BitMap, Rectangle) is currently a no-op. This functionality is core to my needs: I do not have a screen or window to draw to, only a bitmap or equivalent.

Question: How to pass texture to fragment shader?

In OpenGL I'd set up a uniform, but I'm not seeing how to do this here. The obvious way is to simply make my textures members of the object that contains my shaders, then access the texture bytes from within the shader method. But if that's the case, what's the point of the GLTexture class when I've already got the image in a bitmap...

I've reviewed the codebase, and read through the wiki. Not seeing an example stand out, did I miss it?

Attributes to FS contain NaN

From my research it it looks like the FROM and TWO are somehow getting the same value:
image
This result in a div/0 error that results in the attributes getting NaN as a value.

This is based off of master at 7702efb

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.