realtime texture painting

here is the file with textures. the black and white blend between 2 images. here u go. i added my mario grass shader just for kicks.


Attachments

testTexPaint_29.blend (1.08 MB)

so i tweaked the vertex shader and got this.


Attachments

testTexPaint_30.blend (1.26 MB)

Very fun! Thanks for sharing!

this is for laughs


Attachments

testTexPaint_30_orange.blend (1.29 MB)

Impressive! It looks pretty smooth and I have stable, very very stable 60 FPS.

Nice work Cuervo!

had to tamper with it slightly to remove any seams :smiley:

Awesome! This is far the best way to add scars while fighting !!! Can you please help on how to do this on a makehuman mesh with a 1024*1024 texture? I get no errors but the uv’s wrong while running the init script on the makehuman mesh and my texture appears more shiny… I have not used the paint.py script yet.

here is a new version of the shader. i had an idea for adding a uv layer in the middle this layer is maped sideways it changes its uv position with the color of the brush. this moves the uv in the frag shader like it does in the vertex shader. this adds 3 different textures. it looks kinda cool. some one should swap the images and post some cool flesh/skin fx.
example
img 1 is the paint dont mess with it.
img 2 is grass or outer layer
img 3 is rocks or midle layer
img 3 is dirt or inner layer

just change these and thats it. hope u guys like it. i can be useful.

Attachments

testTexPaint_28.blend (564 KB)


Nice work !

The first image is the old file with a new texture and some small tweaks. i did however notice that the texture stretches on a certain axis. but it was still worth the look just to sse the texture. i looks nice.
the second is of course a gory skin layer type file. it was cool too.

i really had fun with this file i’m glad i came to this page thank you

Attachments



here are the files

Attachments

flesh_test.blend (1.57 MB)grass_test.blend (591 KB)

Would it be possible to use this method to also modify physics mesh? And how would than I optimize it? Also, can it use applied force(from physics) as input for deformation somehow?

testTexPaint30 + orange works well on mine.
Others, didn’t work.
err: “cannot convert from ‘4-component vector’ to ‘3-component vector’ of float”

i downloaded the new 2.74rc and i worked fine. i do get those errors aswell. its a simple fix. i was when i was tweaking the settings in the shader. its an easy fix. i also made the flesh image look cooler with this line.

swap it with this one. in frag shader.

vec3 sum3 = vec3(texture2D(texture_color3, vec2(Texcoord2.x * 15. , Texcoord2.y - blend.r - .09 ) ));

@cuervo1003: Thanks. didn’t work.

Tried to fix it. This one works:


import bge
from bge import texture as VideoTexture
from bge import logic as GameLogic
import Rasterizer
import math
from bge import texture

cont = GameLogic.getCurrentController()
own = cont.owner

if "once" not in own:
	own["once"] = True	
	Rasterizer.showMouse(1)

	# size of brush
	brush = bytearray(32*32*4)
	alpha = 0.3
	sigma = 2.5
	ro = 2.0*sigma*sigma
	rgb = [255, 255, 255]
	for x in range(32):
	    for y in range(32):
	        i=y*128+x*4
	        xf=(x-16)+0.5
	        yf=(y-16)+0.5
	        a=int(255*alpha*math.exp(-(xf*xf+yf*yf)/ro))
	        brush[i] = rgb[0]
	        brush[i+1] = rgb[1]
	        brush[i+2] = rgb[2]
	        brush[i+3] = a
	        
	GameLogic.brush = brush

	if not hasattr(GameLogic, 'drawing'):
		GameLogic.tex = VideoTexture.Texture(own,0,0)
		GameLogic.tex.source = VideoTexture.ImageBuff()
		GameLogic.tex.source.load(b'\x00\x00\x00' * (256*256),256,256)
		GameLogic.tex.refresh(False)

	GameLogic.tex.refresh(True)

	VertexShader = """
	varying vec3 eyeVec, normal;
	uniform sampler2D renderedTexture;
	varying vec2 Texcoord1, Texcoord2;

	void main()
	{
		Texcoord1     = gl_MultiTexCoord0.xy;
		Texcoord2     = gl_MultiTexCoord1.xy;
		
		vec2 uv = vec2(Texcoord1.x  , Texcoord1.y );
		vec4 v1 = gl_Vertex ;

		v1.z += texture2D(renderedTexture, uv).b * -.035;
			
		normal = gl_NormalMatrix * gl_Normal;
		vec3 vVertex = vec3(gl_ModelViewMatrix * gl_Vertex);
		eyeVec = -vVertex;
		
		gl_Position = gl_ModelViewProjectionMatrix * v1;
	}
	"""
	 
	FragmentShader = """

	varying vec3  eyeVec, normal;
	uniform sampler2D renderedTexture, texture_color1, texture_color2, texture_color3;
	varying vec2 Texcoord1, Texcoord2;
	   
	void main()
	{  
		vec3 N = normalize(normal);
		vec3 E = normalize(eyeVec);
		float fresnelTerm = pow( max(1.5 * dot(.5 * N,  E), .30), .850);

		//vec3 color;
		vec4 color;
		vec4 blend = vec4(texture2D(renderedTexture,Texcoord1 .xy)); 
		vec3 sum1 = vec3(texture2D(texture_color1, Texcoord1.xy* 2.5)); 
		
		vec3 sum2 = vec3(texture2D(texture_color2, Texcoord1.xy * 5.5 ));	
		
		vec3 sum3 = vec3(texture2D(texture_color3, vec2(Texcoord2.x * 5.5 , Texcoord2.y * 2.0 - blend.r ) ));	
		
		if (blend[0] <= .001)
		{
			color = vec4(sum1, 1.0); 
		}
		
		else
		{
			color = vec4(sum3, 1.0); 
		}
		
		if (blend[0] >= .9)
		{
			color = vec4(sum2, 1.0); 
		}
		

		if (blend[0] <= .001 && blend[0] >= 0.0)
		{
			color = vec4(sum1, 1.0);
		}
		
		//gl_FragColor = (vec4(color - .1, 1.0)  + (.25 - blend * .5) * .5 ) * fresnelTerm * 1.5;
		gl_FragColor = (vec3(color - .1)  + (.25 - blend * .5) * .5 ) * fresnelTerm * 1.5;
	}
	"""
	 
	def shader():
		cont = GameLogic.getCurrentController()
		obj = cont.owner
		mesh = cont.owner.meshes[0]
		for mat in mesh.materials:
			shader = mat.getShader()
			if shader != None:
				if not shader.isValid():
					shader.setSource(VertexShader, FragmentShader, 1)
			shader.setSampler("renderedTexture", 0)
			shader.setSampler("texture_color1", 1)
			shader.setSampler("texture_color2", 2)
			shader.setSampler("texture_color3", 3)
			
	shader() 

if "once" in own:
	ray = cont.sensors['ray']
	click = cont.sensors['click']
	own = cont.owner

	if ray.positive and click.positive:
		UV=ray.hitUV
		x=int(UV[0]*256.0-16.0)
		y=int(UV[1]*256.0-16.0)

		GameLogic.tex.source.plot(GameLogic.brush,32,32,x,y,1)
		GameLogic.tex.refresh(False)
		


hi i was wondering if there is a easy way to determine the percentage of the mesh painted (im working on a Serious game where a patient has to clean a dish with a sponge) i would like to be able to determine if the dish is clean (totally painted).

You can access the texture data from python and check to see if all the values are above a certain threshold. The information you want may be:


img_buff = Some bge.texture.ImageBuff object
RGB_data = img_buff.image.to_list()
for d in RGB_data:
    if d < 0.8:
        'Somewhere wasn't painted'

Thanks for this, I did some work with it today. Really nice code.

Wow, totally epic.
Good job.

very interesting. good work!