Hey, I’m trying to render pixels to a raw image in the canvas by creating an array of Color32s as a buffer then send them to a texture2d. Yeah this is a weird thing to do with Unity but I thought it’d be fun to try, problem is I can’t seem to get anything to actually render to the screen. For whatever reason it just sets the image to a weird transparent gray, I’m wondering if there’s anything I’m doing wrong? Here is my code
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Raycaster : MonoBehaviour
{
public int ScreenWidth = 320;
public int ScreenHeight = 180;
double posX = 22, posY = 12; //x and y start position
double dirX = -1, dirY = 0; //initial direction vector
double planeX = 0, planeY = 0.66; //the 2d raycaster version of camera plane
Color32[] buffer;
public Texture2D[] texture;
public RawImage Screen;
int[,] worldMap;
// Use this for initialization
void Start()
{
buffer = new Color32[ScreenWidth * ScreenHeight];
worldMap = new int[,]
{
{ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,7,7,7,7,7,7,7},
{ 4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,7},
{ 4,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7},
{ 4,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7},
{ 4,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,7},
{ 4,0,4,0,0,0,0,5,5,5,5,5,5,5,5,5,7,7,0,7,7,7,7,7},
{ 4,0,5,0,0,0,0,5,0,5,0,5,0,5,0,5,7,0,0,0,7,7,7,1},
{ 4,0,6,0,0,0,0,5,0,0,0,0,0,0,0,5,7,0,0,0,0,0,0,8},
{ 4,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,7,7,1},
{ 4,0,8,0,0,0,0,5,0,0,0,0,0,0,0,5,7,0,0,0,0,0,0,8},
{ 4,0,0,0,0,0,0,5,0,0,0,0,0,0,0,5,7,0,0,0,7,7,7,1},
{ 4,0,0,0,0,0,0,5,5,5,5,0,5,5,5,5,7,7,7,7,7,7,7,1},
{ 6,6,6,6,6,6,6,6,6,6,6,0,6,6,6,6,6,6,6,6,6,6,6,6},
{ 8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4},
{ 6,6,6,6,6,6,0,6,6,6,6,0,6,6,6,6,6,6,6,6,6,6,6,6},
{ 4,4,4,4,4,4,0,4,4,4,6,0,6,2,2,2,2,2,2,2,3,3,3,3},
{ 4,0,0,0,0,0,0,0,0,4,6,0,6,2,0,0,0,0,0,2,0,0,0,2},
{ 4,0,0,0,0,0,0,0,0,0,0,0,6,2,0,0,5,0,0,2,0,0,0,2},
{ 4,0,0,0,0,0,0,0,0,4,6,0,6,2,0,0,0,0,0,2,2,0,2,2},
{ 4,0,6,0,6,0,0,0,0,4,6,0,0,0,0,0,5,0,0,0,0,0,0,2},
{ 4,0,0,5,0,0,0,0,0,4,6,0,6,2,0,0,0,0,0,2,2,0,2,2},
{ 4,0,6,0,6,0,0,0,0,4,6,0,6,2,0,0,5,0,0,2,0,0,0,2},
{ 4,0,0,0,0,0,0,0,0,4,6,0,6,2,0,0,0,0,0,2,0,0,0,2},
{ 4,4,4,4,4,4,4,4,4,4,1,1,1,2,2,2,2,2,2,3,3,3,3,3}
};
}
// Update is called once per frame
void Update()
{
for (int x = 0; x < ScreenWidth; x++)
{
//calculate ray position and direction
double cameraX = 2 * x / (double)ScreenWidth - 1; //x-coordinate in camera space
double rayDirX = dirX + planeX * cameraX;
double rayDirY = dirY + planeY * cameraX;
//which box of the map we're in
int mapX = (int)posX;
int mapY = (int)posY;
//length of ray from current position to next x or y-side
double sideDistX;
double sideDistY;
//length of ray from one x or y-side to next x or y-side
double deltaDistX = Math.Sqrt(1 + (rayDirY * rayDirY) / (rayDirX * rayDirX));
double deltaDistY = Math.Sqrt(1 + (rayDirX * rayDirX) / (rayDirY * rayDirY));
double perpWallDist;
//what direction to step in x or y-direction (either +1 or -1)
int stepX;
int stepY;
int hit = 0; //was there a wall hit?
int side = 0; //was a NS or a EW wall hit?
//calculate step and initial sideDist
if (rayDirX < 0)
{
stepX = -1;
sideDistX = (posX - mapX) * deltaDistX;
}
else
{
stepX = 1;
sideDistX = (mapX + 1.0 - posX) * deltaDistX;
}
if (rayDirY < 0)
{
stepY = -1;
sideDistY = (posY - mapY) * deltaDistY;
}
else
{
stepY = 1;
sideDistY = (mapY + 1.0 - posY) * deltaDistY;
}
//perform DDA
while (hit == 0)
{
//jump to next map square, OR in x-direction, OR in y-direction
if (sideDistX < sideDistY)
{
sideDistX += deltaDistX;
mapX += stepX;
side = 0;
}
else
{
sideDistY += deltaDistY;
mapY += stepY;
side = 1;
}
//Check if ray has hit a wall
if (worldMap[mapX, mapY] > 0) hit = 1;
}
//Calculate distance of perpendicular ray (Euclidean distance will give fisheye effect!)
if (side == 0) perpWallDist = (mapX - posX + (1 - stepX) / 2) / rayDirX;
else perpWallDist = (mapY - posY + (1 - stepY) / 2) / rayDirY;
//Calculate height of line to draw on screen
int lineHeight = (int)(ScreenHeight / perpWallDist);
//calculate lowest and highest pixel to fill in current stripe
int drawStart = -lineHeight / 2 + ScreenHeight / 2;
if (drawStart < 0) drawStart = 0;
int drawEnd = lineHeight / 2 + ScreenHeight / 2;
if (drawEnd >= ScreenHeight) drawEnd = ScreenHeight - 1;
//texturing calculations
int texNum = worldMap[mapX, mapY] - 1; //1 subtracted from it so that texture 0 can be used!
int texWidth = texture[texNum].width;
int texHeight = texture[texNum].height;
//calculate value of wallX
double wallX; //where exactly the wall was hit
if (side == 0) wallX = posY + perpWallDist * rayDirY;
else wallX = posX + perpWallDist * rayDirX;
wallX -= Math.Floor((wallX));
//x coordinate on the texture
int texX = (int)(wallX * (double)(texWidth));
if (side == 0 && rayDirX > 0) texX = texWidth - texX - 1;
if (side == 1 && rayDirY < 0) texX = texWidth - texX - 1;
for (int y = drawStart; y < drawEnd; y++)
{
int d = y * 256 - ScreenHeight * 128 + lineHeight * 128; //256 and 128 factors to avoid floats
// TODO: avoid the division to speed this up
int texY = ((d * texHeight) / lineHeight) / 256;
Color32 color = (Color32)texture[texNum].GetPixel(texX, texY);
//make color darker for y-sides: R, G and B byte each divided through two with a "shift" and an "and"
if (side == 1)
{
color.r /= 2;
color.g /= 2;
color.b /= 2;
}
buffer[ScreenHeight * y + x] = color;
}
}
DrawBuffer();
for (int x = 0; x < ScreenWidth; x++) for (int y = 0; y < ScreenHeight; y++) buffer[y * x] = Color.black; //clear the buffer
}
void DrawBuffer()
{
Texture2D screen = new Texture2D(ScreenWidth, ScreenHeight);
Screen.texture = screen;
screen.SetPixels32(buffer);
}
}
Is anyone able to shed any light on this for me?