0
\$\begingroup\$

[SOLVED] - The project is here https://drive.google.com/open?id=1-kum0phM_iBMc8xRxYShmCNRWRs6W0Aw

I am using the same vertex shader and pixel shader for my instances. I am sending ONE FLAT array that contains all the instanced chunk bytes that make the cube of the Minecraft terrain. My goal is to make ONE DRAW CALL... Nothing is working. I am able to use an input element that has the specific index of the vertex logged in memory so all of the instances vertexes share the same index. It should be super easy after that to fetch the byte 0 or 1 inside of the flat chunk array that contains all of the data.

It should be working. The indexes of the vertices are perfect. The indexes of the instanced chunks are perfect...

What the h*** is NOT working? It feels as if something is wrong with the array as the chunks bytes are rendered randomly on my computer display. Everything that i see is wrong. I padded all of my structs to send to the shader and padded correctly the InputElements...??? I tried sending an array of Matrices instead... Each Matrix M11 to M44 contains the index of the bytes and I send that as an array to the shader and BAM... nothing is still working... Doing it on the cpu would be completely fine as i've done it a thousand times already.

enter image description here

cbuffer MatrixBuffer :register(b0)
{
	float4x4 world;
	float4x4 view;
	float4x4 proj;
};

cbuffer inData:register(b1)
{		
	int chunkMap[4096];
}

struct VertexInputType
{
    float4 position : POSITION;
	float4 indexPos : POSITION1;
	float4 instancePosition1 : INSTANCEPOSITION1;
};

struct PixelInputType
{
    float4 position : SV_POSITION;
	float4 color : COLOR;
};

float planeSize = 1;

static int mapWidth = 4;
static int mapHeight = 4;
static int mapDepth = 4;

static int tinyChunkWidth = 4;
static int tinyChunkHeight = 4;
static int tinyChunkDepth = 4;

bool IsTransparent(int xMain, int yMain, int zMain, int x, int y, int z)
{	
	int indexMain = xMain + mapWidth * (yMain + mapHeight * zMain);
	int indexSec = x + tinyChunkWidth * (y + tinyChunkHeight * z);

    if ((x < 0) || (y < 0) || (z < 0) || (x >= tinyChunkWidth) || (y >= tinyChunkHeight) || (z >= tinyChunkDepth)) return true;
    {
		return chunkMap[(indexMain * 64) + indexSec] == 0;
    }
}
PixelInputType TextureVertexShader(VertexInputType input)
{  	
	PixelInputType output;

	input.position.w = 1.0f;

	int xMain = 0;
	int yMain = 0;
	int zMain = 0;



xMain = round(fmod((input.instancePosition1.x*10), mapWidth*tinyChunkWidth));
yMain = round(fmod((input.instancePosition1.y*10), mapHeight*tinyChunkHeight));
zMain = round(fmod((input.instancePosition1.z*10), mapDepth*tinyChunkDepth));	

xMain = round(xMain / mapWidth);
yMain = round(yMain / mapHeight);
zMain = round(zMain / mapDepth);

	
	int x = input.indexPos.x;
	int y = input.indexPos.y;
	int z = input.indexPos.z;

	int indexMain = xMain + mapWidth * (yMain + mapHeight * zMain);

	int indexSec = x + tinyChunkWidth * (y + tinyChunkHeight * z);

	int currentByte = chunkMap[(indexMain * 64) + indexSec];
	
	input.position.x += input.instancePosition1.x;
	input.position.y += input.instancePosition1.y;
	input.position.z += input.instancePosition1.z;

	output.position = mul(input.position, world);
	output.position = mul(output.position, view);
	output.position = mul(output.position, proj);

	if (currentByte == 1)
    {		
		output.color = float4(0,1,0,1);
		return output;	
	}
	else
	{

		output.color = float4(0,0,1,1);
		return output;
	}
}

This is my current result. And it doesn't make sense and I don't understand why...

enter image description here

Seriously though. What is going on. I am sending a simple array to the GPU. Whatever padding I put shouldnt really matter since there is a single element in the struct for the buffer. Is it the GPU pipeline that is causing issues? is it because the GPU randomly puts data in the array which doesnt make any sense if it does? It is IMPOSSIBLE that the problem is my index of each vertex because I am setting those up BEFORE even starting rendering, they are setup as an input element Vector4 with x,y,z beeing the index position of the byte.

Or what I am trying is impossible? It shouldn't be unless it's related to some funky things the GPU is doing when instancing objects. Or I am just blind and I don't know what the f*** im coding.

EDIT 2019-03-30: WHAT IT SHOULD LOOK LIKE (down below) - pic of chunk data that are drawn individually - more draw calls as each instance has its own draw calls...But this tiny picture shows instanced chunks with 4096 total instances. Each object created has 64 instances and there is 64 objects. There is 4096 draw calls in here at which point you can argue those aren't really instanced at all but they are! Each instance has its own draw call in order to modify the vertexes and indexes of each instances. It's a very bad programing test and no one should ever attempt this as it's completely useless... I mean, I could probably have better results even without instancing the chunks.

enter image description here

EDIT 2019-03-30: WHAT IT LOOKS RIGHT NOW (down below)- I am almost there but again it's not working yet. I am able to send chunk data another way instead of a constant buffer and it seems to do "half" of the job. I'm gonna keep at it. 1 draw call and i could make the terrain as big as I want it. Same thing with the chunks, 64 objects and 64 instances per object. BUT there is only 64 draw calls here hehe. Of course, I benchmarking at the same time and the final version won't be tiny chunksBytes of 4*4*4 by instances 4*4*4 by objects 4*4*4, they will be bigger.

As you can see, I got some good results finally where the chunks are correctly aligned and it seems that they are in the right position, but the chunks are missing bytes... I am wondering if it is a padding/packing issue because again, I went over the c# script many times to check the index position and it seems fine. Thanks for the response DMGregory. By the way, I am NOW using floats as the inputElements. Each float contains 16 digits that are made up of bytes 1 and 0. Each bytes represent if the chunkBytes faces should be drawn or not. The inputElement is instanced and 4 floats of 16 digits gives me 64 .... wow wait a minute. is this where I am doing it wrong? brb on this

PERLIN CHUNK DATA SENT TO SHADER

nevermind, i am doing it right as I am building the VertexBufferBinding with an array of floats dismantled into a single float containing 16 digits for each slot. In the shader, i am accessing the vertexBinding and it really is giving me the correct float bytes, i think, for each instance. So everything should be ok. but its not ok.

EDIT 2019-03-31: I have changed my shader to this instead.

cbuffer MatrixBuffer :register(b0)
{
	float4x4 world;
	float4x4 view;
	float4x4 proj;
};

struct VertexInputType
{
    float4 position : POSITION;
	float4 indexPos : POSITION1;
	float4 color : COLOR;
	float3 normal : NORMAL;
	float2 tex : TEXCOORD;
	float3 dummyPad : NORMAL1;
	float4 indexPosMain : INSTANCEPOSITION;
	float4 instancePosition1 : INSTANCEPOSITION1;
};

struct PixelInputType
{
	float4 position : SV_POSITION;
	float4 color : COLOR;
	float3 normal : NORMAL;
	float2 tex : TEXCOORD;
};

float planeSize = 0.1f;

static int mapWidth = 4;
static int mapHeight = 4;
static int mapDepth = 4;

static int tinyChunkWidth = 4;
static int tinyChunkHeight = 4;
static int tinyChunkDepth = 4;

//[maxvertexcount(96)] 
PixelInputType TextureVertexShader(VertexInputType input)
{  
	PixelInputType output;
    input.position.w = 1.0f;
				
	//int mainX = input.indexPosMain.x;
	//int mainY = input.indexPosMain.y;
	//int mainZ = input.indexPosMain.z;
	
	int x = (input.indexPos.x);
	int y = (input.indexPos.y);
	int z = (input.indexPos.z);

	float currentMapData;
	float currentByte;

	int currentIndex = x + tinyChunkWidth * (y + tinyChunkHeight * z);

	if(currentIndex >= 0 && currentIndex <= 15)
	{
		currentMapData = input.indexPosMain.x;
		currentIndex = 	currentIndex;
		currentIndex = 15-currentIndex;
	}
	else if(currentIndex >= 16 && currentIndex <= 31)
	{
		currentMapData = input.indexPosMain.y;
		currentIndex = 31 - currentIndex;
		currentIndex = 15-currentIndex;
	}
	else if(currentIndex >= 32 && currentIndex <= 47)
	{
		currentMapData = input.indexPosMain.z;
		currentIndex = 47 - currentIndex;
		currentIndex = 15-currentIndex;
	}
	else if(currentIndex >= 48 && currentIndex <= 63)
	{
		currentMapData = input.indexPosMain.w;
		currentIndex = 63 - currentIndex;
		currentIndex = 15 - currentIndex;
	}

	if(currentIndex == 0)
	{	
		float before = currentMapData * 0.1f;  
		float newIndex1 = round(before);	   
		float lastIndex = before - newIndex1; 
		currentByte = round(lastIndex * 10);			
	}
	else
	{	
		int tempData = currentMapData;
		for(int i = 0;i < 15-currentIndex; i++)
		{			
			tempData = currentMapData * 0.1f;
			currentMapData = round(tempData);
		}

		float before = currentMapData * 0.1f;
		float newIndex1 = round(before);
		float lastIndex = before - newIndex1;
		float otherByte = lastIndex * 10;
		currentByte = round(otherByte);

	}

	int current = currentByte;

	if(current == 1) //current >= 5 || wtf
	{
		input.position.x += input.instancePosition1.x;
		input.position.y += input.instancePosition1.y;
		input.position.z += input.instancePosition1.z;

		output.position = mul(input.position, world);
		output.position = mul(output.position, view);
		output.position = mul(output.position, proj);
	}
	else
	{
		input.position.x = input.instancePosition1.x;
		input.position.y = input.instancePosition1.y;
		input.position.z = input.instancePosition1.z;

		output.position = mul(input.position, world);
		output.position = mul(output.position, view);
		output.position = mul(output.position, proj);
	}

	output.color = input.color;
	output.tex = input.tex;

	output.normal = mul(input.normal, world);
	output.normal = normalize(output.normal);

	return output;
}

EDIT: 2019-04-09 - 04h35am - I was able to make this work.

\$\endgroup\$
  • \$\begingroup\$ Can you try editing your question to walk us through the strategy you're using here, and your understanding of how this should work? Right now a lot of this question is devoted to emphasizing how confused you are, which doesn't really help get a potential answerer up to speed on your technique. Maybe show a test case with a very small number of voxels, so you can show us the exact input data you're using, the expected output, and what output you get instead (annotated with axis labels) so we can try to work out what the pattern or relationship is. \$\endgroup\$ – DMGregory Mar 30 at 8:17
  • \$\begingroup\$ I posted 2 pics showing what it should look like and what it looks like right now with my latest version. Its a benchmarking version so there is nothing fancy, just a chunk in the middle of nowhere with Perlin noise used. I do not have any axis setup yet and haven't used them for as long as I stopped coding in Unity and started working on Sharpdx. I will try to implement that soon but I use the same axis as in Unity for all of my projects. \$\endgroup\$ – Ninekorn Mar 31 at 0:48
  • \$\begingroup\$ I have also posted my question in here to get some more attention. gamedev.net/forums/topic/… \$\endgroup\$ – Ninekorn Mar 31 at 1:46
  • \$\begingroup\$ I added my new shader version as I am now using one Vector4 that i send to the shader with only one vertex buffer binding. The Vector4 xyzw positions each contain a 16 digits that are made up of 0 and 1s. It looks like this in the Vector4: x:101001100111001011 and so on for the yzw . each axis of the vector has different data of course that are made of the chunks bytes 4*4*4. In the shader, I am also retrieving the index Byte of the vertex and calculating between 0 and 63 which index it is and then,i draw with a 1 and put the vertex somewhere else when its a 0. But i get those results up top \$\endgroup\$ – Ninekorn Apr 1 at 2:51
  • 1
    \$\begingroup\$ This isn't about making someone happy, this is about leveraging the experience that's being offered to you. Longtime users of this site have helped refine and answer hundreds of questions each — they have good insights into what a question needs to facilitate useful answers. "Please help" ain't it. People are here because they already want to help, they just need to see on opportunity for how. If you've been asking for help the same way for two and a half years without results, while hundreds of other users are getting useful answers, maybe it's time to try some advice you've been offered. \$\endgroup\$ – DMGregory Apr 9 at 10:56
1
\$\begingroup\$

The project Version 1.0 is here: https://drive.google.com/open?id=1-kum0phM_iBMc8xRxYShmCNRWRs6W0Aw

The goal is achieved. It was to modify the vertex position inside of a Vertex Shader with using Vertex Binding Elements. The vertex binding is used both for storing the index of each byte (to which each vertex is assigned to) inside of each chunk instanced or not and also used to send the instance bytes in the form of integers.

In the end, the positions of each vertex is manipulated inside of the vertex shader but they are NOT removed from the scene. Hence why I will work on Version 1.1 and try to incorporate a Geometry shader to nullify triangles/faces that are not needed. In order to do that, I need to ask another question.

Oh... I forgot to mention one very important fact. In order to run the project, you need an Oculus Rift VR headset. Very soon, I will build the same project without the need of the VR headset. It does run faster without the headset as there is no need to draw twice for each eyes.

I didn't put a license on my shader and whatnot because I got bored searching on how to put the project on GitHub + I am the TUCO of coding, so every part of my code here and there uses parts of someone elses code so in the end, I didn't knew what to put a license on.

Special thanks to Craig Perko for creating the Minecraft Terrain Tutorial series 1 & 2 on YouTube.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.