Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adding a Skybox #7

Open
rontrek opened this issue Jul 24, 2019 · 6 comments
Open

adding a Skybox #7

rontrek opened this issue Jul 24, 2019 · 6 comments

Comments

@rontrek
Copy link

rontrek commented Jul 24, 2019

Hi, I see that the forum is now read only and noted to post here on GitHub for questions, so in particular I'm trying to create a background skybox for a twopointfive level. I did search for previous related post here:

https://impactjs.com/forums/impact-engine/impact-1-24-pseudo-3d-web-audio

but with no luck and somehow can't get it to work. What I have done so far is cleared a part of the ceiling assuming it will be drawn there.

main.js

init: function() {
...
this.skyboxImage = new ig.Image( 'media/skybox.png' );
this.skyboxImage.width = screen.width;
this.skyboxImage.height = screen.height;
this.skyboxQuad = new tpf.HudTile( this.skyboxImage, 0, screen.width, screen.height);
this.skyboxQuad.setPosition(0, 0, 0);		

...
...
...

drawWorld: function() {
this.skyboxQuad.draw();
this.parent();
}
@Igecode
Copy link

Igecode commented Jul 24, 2019

I think your skybox need to be un cube.
I've wrote this for a game prototype few years ago. I think it's a "good" base to solve your problem (I think it's not usable without somme work for you).
It use an entity to work with weltmeister :

PLUGIN:

ig.module(
	'plugins.igecode.world.skybox'
)
.requires(
	'impact.image',
	'plugins.twopointfive.renderer.quad'
)
.defines(function(){


ig.Skybox = ig.Class.extend({
	
	boxSize: 4096,
	boxPos: {x: 0, y: 0, z:0},

	tileSize: 32,
	tileScale: 1,

	textures: {
		/* sky list or tweak it for use image with init(settings)*/
		black: new ig.Image('media/skydomes/black.png'),
		bluesky: new ig.Image('media/skydomes/bluesky.jpg'),
		test: new ig.Image('media/skydomes/test.png')
	},

	boxFaces: null,
	image: null,

	init:function(settings){
		if(settings != null) {
			if(settings.image && this.textures[settings.image]){
				this.image = this.textures[settings.image];
			}

			this.boxPos = {x:settings.x || 0, y:settings.z || 0, z:settings.y || 0};
			this.boxSize = settings.boxSize || 2048
			this.tileSize = settings.tileSize || 512
		}

		this.tileScale = this.boxSize / this.tileSize;

		if(this.image == null) {
			this.image = this.textures.black;
		}

		// Create faces
		this.createGeometry();
	},

	createGeometry: function(){
		// creates tiles
		this.boxFaces = [
			new tpf.Tile( this.image, 0, this.tileSize, this.tileSize, this.tileScale ),
			new tpf.Tile( this.image, 5, this.tileSize, this.tileSize, this.tileScale ),
			new tpf.Tile( this.image, 2, this.tileSize, this.tileSize, this.tileScale ),
			new tpf.Tile( this.image, 1, this.tileSize, this.tileSize, this.tileScale ),
			new tpf.Tile( this.image, 4, this.tileSize, this.tileSize, this.tileScale ),
			new tpf.Tile( this.image, 3, this.tileSize, this.tileSize, this.tileScale ),
		];

		// face 1 (front)
		this.boxFaces[0].quad.setPosition(
			this.boxPos.x,
			this.boxPos.y,
			this.boxPos.z + this.boxSize/2
		);
		this.boxFaces[0].quad.setRotation(0, Math.PI, 0);
		

		// face 2 (left)
		this.boxFaces[1].quad.setPosition(
			this.boxPos.x - this.boxSize/2,
			this.boxPos.y,
			this.boxPos.z 
		);
		this.boxFaces[1].quad.setRotation(0, Math.PI/2, 0);

		// face 3 (back)
		this.boxFaces[2].quad.setPosition(
			this.boxPos.x,
			this.boxPos.y,
			this.boxPos.z - this.boxSize/2
		);
		
		// face 4 (right)
		this.boxFaces[3].quad.setPosition(
			this.boxPos.x + this.boxSize/2,
			this.boxPos.y,
			this.boxPos.z 
		);
		this.boxFaces[3].quad.setRotation(0, -Math.PI/2, 0);

		// face 5 (top)
		this.boxFaces[4].quad.setPosition(
			this.boxPos.x,
			this.boxPos.y + this.boxSize/2,
			this.boxPos.z 
		);
		this.boxFaces[4].quad.setRotation(-Math.PI/2, Math.PI, Math.PI/2);

		// face 6 (bottom)
		this.boxFaces[5].quad.setPosition(
			this.boxPos.x,
			this.boxPos.y - this.boxSize/2,
			this.boxPos.z 
		);
		this.boxFaces[5].quad.setRotation(Math.PI/2, -Math.PI, 0);
	},


	draw: function(){
		if(!this.boxFaces) {
			this.createGeometry();
		}

		var mesh = new tpf.TileMesh(this.boxFaces),
			renderer = ig.system.renderer;

		renderer.pushMesh(mesh);

		renderer.setProgram(renderer.programFog);

	}
});
});

ENTITY

ig.module(
	'game.entities.skybox-params'
)
.requires(
	'impact.entity'
)
.defines(function(){

EntitySkyboxParams = ig.Entity.extend({
	type: ig.Entity.TYPE.NONE,
	checkAgainst: ig.Entity.TYPE.NONE,
	collides: ig.Entity.COLLIDES.NEVER,

	size: {x: 8, y: 8},
	boxSize: 2048,
	
	_wmDrawBox: true,
	_wmBoxColor: '#88f',
	
	init: function(x, y, settings){
		this.parent(x, y, settings);
	},

	update: function(){},

	draw: function(){
		if(!ig.global.wm){
			return;
		}

		var x = (this.pos.x-this.boxSize/2+this.size.x/2-ig.game.screen.x)*ig.system.scale,
			y = (this.pos.y-this.boxSize/2+this.size.y/2-ig.game.screen.y)*ig.system.scale,
			boxSize = this.boxSize*ig.system.scale,
			alpha = (this == ig.game.entities.selectedEntity)?1: 0.2;

		var ctx = ig.system.context;
		ctx.globalAlpha = alpha;
		
		ctx.lineWidth = 1;
		ctx.strokeStyle = this._wmBoxColor;
		ctx.stroke();
		ctx.strokeRect( x, y, this.boxSize * ig.system.scale, this.boxSize * ig.system.scale );
		ctx.globalAlpha = 1;
	}
});
});

GAME EXTEND :

ig.module(
	'plugins.igecode.game'
)
.requires(
	'plugins.twopointfive.game',
	'plugins.igecode.world.skybox'
)
.defines(function(){ "use strict";


ig.GameExtend = tpf.Game.extend({

	skybox: null,

	clearLevel: function() {
		this.parent();

		this.skybox = null;
	},


	loadLevel: function( data ) {
		this.parent();
		
		// creation du skybox
		// Find the info entity
		var skyboxParams = null;
		for( var i=0; i<data.entities.length; i++ ) {
			if( data.entities[i].settings && data.entities[i].type == 'EntitySkyboxParams' ) {
				skyboxParams = data.entities[i].settings;
				skyboxParams.x = data.entities[i].x;
				skyboxParams.y = data.entities[i].y;
			}
		}

		if(skyboxParams != null) {
			this.skybox = new ige.Skybox(skyboxParams);
		}
	},

	drawWorld: function() {
		this.parent();

		if(this.skybox != null) {
			this.skybox.draw();
		}

	}
});
});

@rontrek
Copy link
Author

rontrek commented Jul 25, 2019

Awesome, Thanks a lot! @SilvRO 😃

one small issue I noticed is it is affected by fog, so I have to turn it off. It would be nice though to get this to work with fog.

Anyways, really appreciate this and got it working. thanks again 👍 👍 👍

@Igecode
Copy link

Igecode commented Jul 25, 2019

The quads are very far away from the camera. You need some tweak to disable fog only on skybox.

I'm glad to have helped you 😃

@rontrek
Copy link
Author

rontrek commented Jul 25, 2019

I see and I would assume that would involve tweaking the fog shader. @phoboslab is there a current workaround to exclude an entity/quad set from fog?

Another minor thing would be attaching or parenting the skybox to the player/camera to get that endless horizon effect. I'm fairly new to impact/tpf and tried to copy the x and y player position to the box position and it is not moving at all.. looks like that's not how it works. any tips for that?

@Igecode
Copy link

Igecode commented Jul 25, 2019

My code was really for testing. Normally a skybox is not a "physical" entity that the player can touch. I think we need to review the integration of the skybox to do this. A 3D pass for the skybox with fixed origin and camera angle, then a pass for the level.
For fog, perhaps pass a parameter to the shader fragment to disable it (impact\lib\plugins\twopointfive\renderer\render.js: tpf.Renderer.Shaders.vertex.FragmentWithFog). And go up to the Quad object to pass the parameter.

@rontrek
Copy link
Author

rontrek commented Jul 25, 2019

Ok got it. Yes, agreed and what I have proposed there is not having to use shaders as much as possible as this is the go-to method which was used before shaders became available, and that is setting up a large skybox following camera or using pivot attached to player camera. I think your solution here is more practical and simple, but I don't mind going for a shader version either.

As for the fog, I finally figured out a workaround which just involves depth. With the fog near and far default setting to 128 and 512 respectively, I just set the boxSize a little bit bigger around 8000 (so the sky looks bigger/farther with a huge margin just to make sure) and added this on the fog shader.

if(depth > 2000.0) fogFactor = 0.0;

or just 1000, might need some adjustment depending on the map setup, but it works. I still have no clue with interacting with custom quads and passing parameters to shader on Impact, but would be curious to know how this can be done, particularly with entities that are not far but is not affected with fog (items, entities, powerups, etc.).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants