Render capture for Krom
This commit is contained in:
parent
07ea79b376
commit
b1f4c27567
|
@ -34,9 +34,9 @@ void main() {
|
|||
float weight = 0.5 * clamp(1.0 - sqrt(delta) * SMAA_REPROJECTION_WEIGHT_SCALE, 0.0, 1.0);
|
||||
|
||||
// Blend the pixels according to the calculated weight:
|
||||
fragColor.rgb = mix(current.rgb, previous.rgb, weight);
|
||||
fragColor = vec4(mix(current.rgb, previous.rgb, weight), 1.0);
|
||||
#else
|
||||
vec4 previous = texture(tex2, texCoord);
|
||||
fragColor = mix(current.rgb, previous.rgb, 0.5);
|
||||
fragColor = vec4(mix(current.rgb, previous.rgb, 0.5), 1.0);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -21,12 +21,6 @@ class SpaceArmory extends Trait {
|
|||
|
||||
static var first = true;
|
||||
|
||||
#if js
|
||||
static var patchTime = 0.0;
|
||||
static var lastMtime:Dynamic = null;
|
||||
static var lastSize:Dynamic;
|
||||
#end
|
||||
|
||||
public function new() {
|
||||
super();
|
||||
|
||||
|
@ -43,8 +37,8 @@ class SpaceArmory extends Trait {
|
|||
|
||||
if (first) {
|
||||
first = false;
|
||||
#if (js && kha_webgl)
|
||||
electronRenderCapture();
|
||||
#if (kha_krom && arm_render)
|
||||
renderCapture();
|
||||
#end
|
||||
}
|
||||
}
|
||||
|
@ -112,9 +106,10 @@ class SpaceArmory extends Trait {
|
|||
}
|
||||
#end
|
||||
}
|
||||
var time = 0.0;
|
||||
|
||||
#if (js && kha_webgl)
|
||||
static var time = 0.0;
|
||||
static var lastMtime:Dynamic = null;
|
||||
function reloadOnUpdate() {
|
||||
// Reload page on kha.js rewrite
|
||||
var khaPath = "kha.js";
|
||||
|
@ -131,58 +126,33 @@ class SpaceArmory extends Trait {
|
|||
}
|
||||
xhr.send();
|
||||
}
|
||||
#end
|
||||
|
||||
public static function getRenderResult():js.html.Uint8Array {
|
||||
var gl = kha.SystemImpl.gl;
|
||||
var w = gl.drawingBufferWidth;
|
||||
var h = gl.drawingBufferHeight;
|
||||
var pixels = new js.html.Uint8Array(w * h * 4);
|
||||
gl.readPixels(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight, js.html.webgl.GL.RGBA, js.html.webgl.GL.UNSIGNED_BYTE, pixels);
|
||||
return pixels;
|
||||
// var bytes = haxe.io.Bytes.ofData(pixels.buffer);
|
||||
// var pngdata = armory.trait.internal.png.Tools.buildRGB(w, h, bytes);
|
||||
// var output = new haxe.io.BytesOutput();
|
||||
// var writer = new armory.trait.internal.png.Writer(output);
|
||||
// writer.write(pngdata);
|
||||
// return output.getBytes();
|
||||
}
|
||||
|
||||
function electronRenderCapture() {
|
||||
var electron = untyped __js__('window && window.process && window.process.versions["electron"]');
|
||||
if (electron) {
|
||||
untyped __js__('var fs = require("fs");');
|
||||
|
||||
App.notifyOnUpdate(function() {
|
||||
patchTime += iron.system.Time.delta;
|
||||
|
||||
if (patchTime > 0.2) {
|
||||
patchTime = 0;
|
||||
var repatch = false;
|
||||
untyped __js__('
|
||||
if (fs.existsSync(__dirname + "/" + "render.msg")) {
|
||||
{0} = true;
|
||||
fs.unlinkSync(__dirname + "/" + "render.msg");
|
||||
}'
|
||||
, repatch);
|
||||
|
||||
if (repatch) {
|
||||
var pixels = getRenderResult();
|
||||
untyped __js__('
|
||||
fs.writeFileSync(__dirname + "/render.bin", new Buffer({0}));
|
||||
', pixels);
|
||||
var w = kha.SystemImpl.gl.drawingBufferWidth;
|
||||
var h = kha.SystemImpl.gl.drawingBufferHeight;
|
||||
trace("__arm|render" + "|" + w + "|" + h);
|
||||
}
|
||||
// Compare mtime and size of file
|
||||
// untyped __js__('fs.stat(__dirname + "/" + {0} + ".arm", function(err, stats) {', Scene.active.raw.name);
|
||||
// untyped __js__(' if ({0} > stats.mtime || {0} < stats.mtime || {1} !== stats.size) { if ({0} !== undefined) { {2} = true; } {0} = stats.mtime; {1} = stats.size; }', lastMtime, lastSize, repatch);
|
||||
// if (repatch) {
|
||||
#if (kha_krom && arm_render)
|
||||
static var frame = 0;
|
||||
function renderCapture() {
|
||||
App.notifyOnRender(function(g:kha.graphics4.Graphics) {
|
||||
frame++;
|
||||
if (frame >= 3) {
|
||||
var pd = iron.Scene.active.cameras[0].data.pathdata;
|
||||
var tex = pd.renderTargets.get("capture").image;
|
||||
if (tex != null) {
|
||||
var pixels = tex.getPixels();
|
||||
Krom.fileSaveBytes("render.bin", pixels.getData());
|
||||
// var bo = new haxe.io.BytesOutput();
|
||||
// var rgb = haxe.io.Bytes.alloc(tex.width * tex.height * 3);
|
||||
// for (i in 0...tex.width * tex.height) {
|
||||
// rgb.set(i * 3 + 0, pixels.get(i * 4 + 2));
|
||||
// rgb.set(i * 3 + 1, pixels.get(i * 4 + 1));
|
||||
// rgb.set(i * 3 + 2, pixels.get(i * 4 + 0));
|
||||
// }
|
||||
// untyped __js__('});');
|
||||
// var pngwriter = new armory.format.png.Writer(bo);
|
||||
// pngwriter.write(armory.format.png.Tools.buildRGB(tex.width, tex.height, rgb));
|
||||
// Krom.fileSaveBytes("render.png", bo.getBytes().getData());
|
||||
}
|
||||
});
|
||||
}
|
||||
kha.System.requestShutdown();
|
||||
}
|
||||
});
|
||||
}
|
||||
#end
|
||||
}
|
||||
|
|
|
@ -21,14 +21,6 @@ def parse_operator(text):
|
|||
bpy.context.object.select = False
|
||||
bpy.context.scene.objects[cmd[2]].select = True
|
||||
bpy.context.scene.objects.active = bpy.context.scene.objects[cmd[2]]
|
||||
elif cmd[1] == 'render':
|
||||
import numpy
|
||||
data = numpy.fromfile(arm.utils.get_fp_build() + '/html5/render.bin', dtype=numpy.uint8)
|
||||
data = data.astype(float)
|
||||
data = numpy.divide(data, 255)
|
||||
image = bpy.data.images.new("Render Result", width=int(cmd[2]), height=int(cmd[3]))
|
||||
image.pixels = data
|
||||
return
|
||||
|
||||
def send_operator(op):
|
||||
# Try to translate operator directly to armory
|
||||
|
|
|
@ -62,6 +62,23 @@ def on_scene_update_post(context):
|
|||
# op_changed(last_operator, bpy.context.object)
|
||||
# last_operator = None
|
||||
|
||||
if state.is_render:
|
||||
fp = arm.utils.get_fp_build()
|
||||
resx, resy = arm.utils.get_render_resolution(arm.utils.get_active_scene())
|
||||
if os.path.isfile(fp + '/render.bin') and os.path.getsize(fp + '/render.bin') == resx * resy * 4:
|
||||
import numpy
|
||||
data = numpy.fromfile(fp + '/render.bin', dtype=numpy.uint8)
|
||||
# data = data.astype(float)
|
||||
data = numpy.divide(data, 255)
|
||||
n = "Render Result"
|
||||
if n in bpy.data.images and bpy.data.images[n].size[0] == resx and bpy.data.images[n].size[1] == resy:
|
||||
bpy.data.images[n].pixels = data
|
||||
else:
|
||||
image = bpy.data.images.new("Render Result", width=resx, height=resy)
|
||||
image.pixels = data
|
||||
state.is_render = False
|
||||
os.remove(fp + '/render.bin')
|
||||
|
||||
# Player running
|
||||
state.krom_running = False
|
||||
if not state.is_paused and bpy.context.screen != None:
|
||||
|
|
|
@ -217,9 +217,11 @@ def compile_project(target_name=None, is_publish=False, watch=False, patch=False
|
|||
else:
|
||||
return subprocess.Popen(cmd)
|
||||
|
||||
def build_project(is_play=False, is_publish=False, in_viewport=False, target=None):
|
||||
def build_project(is_play=False, is_publish=False, is_render=False, in_viewport=False, target=None):
|
||||
wrd = bpy.data.worlds['Arm']
|
||||
|
||||
state.is_render = is_render
|
||||
|
||||
# Set target
|
||||
if target == None:
|
||||
state.target = wrd.arm_project_target.lower()
|
||||
|
@ -357,7 +359,7 @@ def get_khajs_path(in_viewport, target):
|
|||
else: # Browser
|
||||
return arm.utils.build_dir() + '/html5/kha.js'
|
||||
|
||||
def play_project(in_viewport):
|
||||
def play_project(in_viewport, is_render=False):
|
||||
global scripts_mtime
|
||||
wrd = bpy.data.worlds['Arm']
|
||||
|
||||
|
@ -370,7 +372,7 @@ def play_project(in_viewport):
|
|||
state.target = runtime_to_target(in_viewport)
|
||||
|
||||
# Build data
|
||||
build_project(is_play=True, in_viewport=in_viewport, target=state.target)
|
||||
build_project(is_play=True, is_render=is_render, in_viewport=in_viewport, target=state.target)
|
||||
state.in_viewport = in_viewport
|
||||
|
||||
khajs_path = get_khajs_path(in_viewport, state.target)
|
||||
|
@ -450,8 +452,12 @@ def on_compiled(mode): # build, play, play_viewport, publish
|
|||
webbrowser.open(html5_app_path)
|
||||
elif wrd.arm_play_runtime == 'Krom':
|
||||
krom_location, krom_path = arm.utils.krom_paths()
|
||||
os.chdir(krom_location)
|
||||
state.playproc = subprocess.Popen([krom_path, arm.utils.get_fp_build() + '/window/krom', arm.utils.get_fp_build() + '/window/krom-resources', '--nosound'], stderr=subprocess.PIPE)
|
||||
# os.chdir(krom_location)
|
||||
os.chdir(arm.utils.get_fp_build())
|
||||
args = [krom_path, arm.utils.get_fp_build() + '/window/krom', arm.utils.get_fp_build() + '/window/krom-resources', '--nosound']
|
||||
# if state.is_render:
|
||||
# args.append('--nowindow')
|
||||
state.playproc = subprocess.Popen(args, stderr=subprocess.PIPE)
|
||||
watch_play()
|
||||
|
||||
def clean_cache():
|
||||
|
@ -516,5 +522,4 @@ def publish_project():
|
|||
assets.invalidate_enabled = True
|
||||
|
||||
def get_render_result():
|
||||
with open(arm.utils.get_fp_build() + '/html5/render.msg', 'w') as f:
|
||||
pass
|
||||
play_project(False, is_render=True)
|
||||
|
|
|
@ -196,6 +196,7 @@ def make_deferred(cam):
|
|||
|
||||
if cam.rp_supersampling == '4':
|
||||
links.new(nodes[last_node].outputs[0], nodes['SS Resolve'].inputs[0])
|
||||
last_node = 'SS Resolve'
|
||||
if cam.rp_antialiasing == 'SMAA':
|
||||
links.new(nodes['Reroute.014'].outputs[0], nodes['SMAA'].inputs[1])
|
||||
links.new(nodes['Reroute.014'].outputs[0], nodes['SS Resolve'].inputs[2])
|
||||
|
@ -209,6 +210,15 @@ def make_deferred(cam):
|
|||
links.new(nodes['Reroute.008'].outputs[0], nodes['Draw Compositor'].inputs[1])
|
||||
links.new(nodes['Reroute.008'].outputs[0], nodes['SS Resolve'].inputs[2])
|
||||
|
||||
if cam.rp_rendercapture:
|
||||
# links.new(nodes[last_node].outputs[0], nodes['CopyCapture'].inputs[0])
|
||||
fb = nodes['Framebuffer']
|
||||
cc = nodes['CopyCapture']
|
||||
cn = nodes['Capture']
|
||||
for l in fb.outputs[0].links:
|
||||
if l.to_node != cc:
|
||||
links.new(cn.outputs[0], l.to_socket)
|
||||
|
||||
def make_deferred_plus(cam):
|
||||
pass
|
||||
|
||||
|
|
|
@ -13,3 +13,4 @@ compileproc_success = False
|
|||
play_area = None
|
||||
krom_running = False
|
||||
is_paused = False
|
||||
is_render = False
|
||||
|
|
|
@ -364,6 +364,7 @@ def init_properties():
|
|||
bpy.types.Camera.rp_dfao = bpy.props.BoolProperty(name="DFAO", description="Distance field ambient occlusion", default=False)
|
||||
bpy.types.Camera.rp_dfrs = bpy.props.BoolProperty(name="DFRS", description="Distance field ray-traced shadows", default=False)
|
||||
bpy.types.Camera.rp_bloom = bpy.props.BoolProperty(name="Bloom", description="Bloom processing", default=False, update=update_renderpath)
|
||||
bpy.types.Camera.rp_rendercapture = bpy.props.BoolProperty(name="Render Capture", description="Save output as render result", default=False, update=update_renderpath)
|
||||
bpy.types.Camera.rp_motionblur = EnumProperty(
|
||||
items=[('None', 'None', 'None'),
|
||||
('Basic', 'Basic', 'Basic'),
|
||||
|
|
|
@ -43,6 +43,7 @@ def set_preset(self, context, preset):
|
|||
cam.rp_dfrs = False
|
||||
cam.rp_dfao = False
|
||||
cam.rp_bloom = False
|
||||
cam.rp_rendercapture = False
|
||||
cam.rp_motionblur = 'None'
|
||||
elif preset == 'Forward':
|
||||
cam.rp_renderer = 'Forward'
|
||||
|
@ -69,6 +70,7 @@ def set_preset(self, context, preset):
|
|||
cam.rp_dfrs = False
|
||||
cam.rp_dfao = False
|
||||
cam.rp_bloom = False
|
||||
cam.rp_rendercapture = False
|
||||
cam.rp_motionblur = 'None'
|
||||
elif preset == 'Deferred':
|
||||
cam.rp_renderer = 'Deferred'
|
||||
|
@ -94,6 +96,7 @@ def set_preset(self, context, preset):
|
|||
cam.rp_dfrs = False
|
||||
cam.rp_dfao = False
|
||||
cam.rp_bloom = False
|
||||
cam.rp_rendercapture = False
|
||||
cam.rp_motionblur = 'None'
|
||||
elif preset == 'Max':
|
||||
cam.rp_renderer = 'Deferred'
|
||||
|
@ -119,6 +122,7 @@ def set_preset(self, context, preset):
|
|||
cam.rp_dfrs = False
|
||||
cam.rp_dfao = False
|
||||
cam.rp_bloom = False
|
||||
cam.rp_rendercapture = False
|
||||
cam.rp_motionblur = 'None'
|
||||
elif preset == 'Render Capture':
|
||||
cam.rp_renderer = 'Deferred'
|
||||
|
@ -147,6 +151,7 @@ def set_preset(self, context, preset):
|
|||
cam.rp_dfrs = False
|
||||
cam.rp_dfao = False
|
||||
cam.rp_bloom = False
|
||||
cam.rp_rendercapture = True
|
||||
cam.rp_motionblur = 'None'
|
||||
wrd.lighting_model = 'Cycles'
|
||||
wrd.generate_pcss_state = 'On'
|
||||
|
@ -174,6 +179,7 @@ def set_preset(self, context, preset):
|
|||
cam.rp_dfrs = False
|
||||
cam.rp_dfao = False
|
||||
cam.rp_bloom = False
|
||||
cam.rp_rendercapture = False
|
||||
cam.rp_motionblur = 'None'
|
||||
elif preset == 'VR Low':
|
||||
cam.rp_renderer = 'Forward'
|
||||
|
@ -200,6 +206,7 @@ def set_preset(self, context, preset):
|
|||
cam.rp_dfrs = False
|
||||
cam.rp_dfao = False
|
||||
cam.rp_bloom = False
|
||||
cam.rp_rendercapture = False
|
||||
cam.rp_motionblur = 'None'
|
||||
elif preset == 'Mobile Low':
|
||||
cam.rp_renderer = 'Forward'
|
||||
|
@ -226,6 +233,7 @@ def set_preset(self, context, preset):
|
|||
cam.rp_dfrs = False
|
||||
cam.rp_dfao = False
|
||||
cam.rp_bloom = False
|
||||
cam.rp_rendercapture = False
|
||||
cam.rp_motionblur = 'None'
|
||||
elif preset == 'Grease Pencil':
|
||||
cam.rp_renderer = 'Forward'
|
||||
|
@ -251,6 +259,7 @@ def set_preset(self, context, preset):
|
|||
cam.rp_dfrs = False
|
||||
cam.rp_dfao = False
|
||||
cam.rp_bloom = False
|
||||
cam.rp_rendercapture = False
|
||||
cam.rp_motionblur = 'None'
|
||||
|
||||
updating_preset = False
|
||||
|
@ -335,6 +344,7 @@ class GenRPDataPropsPanel(bpy.types.Panel):
|
|||
layout.prop(dat, "rp_dfrs")
|
||||
layout.prop(dat, "rp_bloom")
|
||||
layout.prop(dat, "rp_motionblur")
|
||||
layout.prop(dat, "rp_rendercapture")
|
||||
|
||||
class PropsRPDataPropsPanel(bpy.types.Panel):
|
||||
bl_label = "Armory Render Props"
|
||||
|
|
|
@ -740,10 +740,15 @@ class ArmoryRenderButton(bpy.types.Operator):
|
|||
bl_label = 'Render'
|
||||
|
||||
def execute(self, context):
|
||||
if state.playproc == None:
|
||||
self.report({"ERROR"}, "Run Armory player in electron window first")
|
||||
return {"CANCELLED"}
|
||||
if state.playproc != None:
|
||||
make.stop_project()
|
||||
if bpy.data.worlds['Arm'].arm_play_runtime != 'Krom':
|
||||
bpy.data.worlds['Arm'].arm_play_runtime = 'Krom'
|
||||
if bpy.data.cameras[0].rp_preset != 'Render Capture':
|
||||
bpy.data.cameras[0].rp_preset = 'Render Capture'
|
||||
assets.invalidate_enabled = False
|
||||
make.get_render_result()
|
||||
assets.invalidate_enabled = True
|
||||
return{'FINISHED'}
|
||||
|
||||
# Play button in 3D View panel
|
||||
|
|
|
@ -89,6 +89,9 @@ project.addSources('Sources');
|
|||
if enable_dce:
|
||||
f.write("project.addParameter('-dce full');")
|
||||
|
||||
if state.is_render:
|
||||
assets.add_khafile_def('arm_render')
|
||||
|
||||
shaderload = state.target == 'krom' or state.target == 'html5'
|
||||
if wrd.arm_cache_compiler and shaderload and not is_publish:
|
||||
# Load shaders manually
|
||||
|
|
Binary file not shown.
Binary file not shown.
Loading…
Reference in a new issue